--- loncom/interface/domainprefs.pm 2017/12/06 23:41:19 1.321
+++ loncom/interface/domainprefs.pm 2021/05/28 01:26:02 1.383
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.321 2017/12/06 23:41:19 raeburn Exp $
+# $Id: domainprefs.pm,v 1.383 2021/05/28 01:26:02 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -104,7 +104,7 @@ $datatable - HTML containing form eleme
In the case of course requests, radio buttons are displayed for each institutional
affiliate type (and also default, and _LC_adv) for each of the course types
-(official, unofficial, community, textbook, and placement).
+(official, unofficial, community, textbook, placement, and lti).
In each case the radio buttons allow the selection of one of four values:
0, approval, validate, autolimit=N (where N is blank, or a positive integer).
@@ -176,6 +176,7 @@ use Locale::Language;
use DateTime::TimeZone;
use DateTime::Locale;
use Time::HiRes qw( sleep );
+use Net::CIDR;
my $registered_cleanup;
my $modified_urls;
@@ -219,9 +220,10 @@ sub handler {
'serverstatuses','requestcourses','helpsettings',
'coursedefaults','usersessions','loadbalancing',
'requestauthor','selfenrollment','inststatus',
- 'ltitools','ssl','trust','lti'],$dom);
+ 'ltitools','ssl','trust','lti','privacy','passwords',
+ 'proctoring','wafproxy'],$dom);
my %encconfig =
- &Apache::lonnet::get_dom('encconfig',['ltitools','lti'],$dom);
+ &Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring'],$dom);
if (ref($domconfig{'ltitools'}) eq 'HASH') {
if (ref($encconfig{'ltitools'}) eq 'HASH') {
foreach my $id (keys(%{$domconfig{'ltitools'}})) {
@@ -246,12 +248,25 @@ sub handler {
}
}
}
- my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
- 'autoupdate','autocreate','directorysrch','contacts',
- 'usercreation','selfcreation','usermodification','scantron',
- 'requestcourses','requestauthor','coursecategories',
- 'serverstatuses','helpsettings','coursedefaults',
- 'ltitools','selfenrollment','usersessions','ssl','trust','lti');
+ if (ref($domconfig{'proctoring'}) eq 'HASH') {
+ if (ref($encconfig{'proctoring'}) eq 'HASH') {
+ foreach my $provider (keys(%{$domconfig{'proctoring'}})) {
+ if ((ref($domconfig{'proctoring'}{$provider}) eq 'HASH') &&
+ (ref($encconfig{'proctoring'}{$provider}) eq 'HASH')) {
+ foreach my $item ('key','secret') {
+ $domconfig{'proctoring'}{$provider}{$item} = $encconfig{'proctoring'}{$provider}{$item};
+ }
+ }
+ }
+ }
+ }
+ my @prefs_order = ('rolecolors','login','defaults','wafproxy','passwords','quotas',
+ 'autoenroll','autoupdate','autocreate','directorysrch',
+ 'contacts','privacy','usercreation','selfcreation',
+ 'usermodification','scantron','requestcourses','requestauthor',
+ 'coursecategories','serverstatuses','helpsettings','coursedefaults',
+ 'ltitools','proctoring','selfenrollment','usersessions','ssl',
+ 'trust','lti');
my %existing;
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
@@ -291,13 +306,36 @@ sub handler {
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,
},
+ 'wafproxy' =>
+ { text => 'Web Application Firewall/Reverse Proxy',
+ help => 'Domain_Configuration_WAF_Proxy',
+ header => [{col1 => 'Domain(s)',
+ col2 => 'Servers and WAF/Reverse Proxy alias(es)',
+ },
+ {col1 => 'Domain(s)',
+ col2 => 'WAF Configuration',}],
+ print => \&print_wafproxy,
+ modify => \&modify_wafproxy,
+ },
+ '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',
@@ -352,6 +390,8 @@ sub handler {
col2 => 'Value',},
{col1 => 'Recipient(s) for notifications',
col2 => 'Value',},
+ {col1 => 'Nightly status check e-mail',
+ col2 => 'Settings',},
{col1 => 'Ask helpdesk form settings',
col2 => 'Value',},],
print => \&print_contacts,
@@ -392,11 +432,12 @@ sub handler {
modify => \&modify_usermodification,
},
'scantron' =>
- { text => 'Bubblesheet format file',
+ { text => 'Bubblesheet format',
help => 'Domain_Configuration_Scantron_Format',
- header => [ {col1 => 'Item',
- col2 => '',
- }],
+ header => [ {col1 => 'Bubblesheet format file',
+ col2 => ''},
+ {col1 => 'Bubblesheet data upload formats',
+ col2 => 'Settings'}],
print => \&print_scantron,
modify => \&modify_scantron,
},
@@ -482,10 +523,16 @@ sub handler {
modify => \&modify_selfenrollment,
},
'privacy' =>
- {text => 'User Privacy',
+ {text => 'Availability of User Information',
help => 'Domain_Configuration_User_Privacy',
- header => [{col1 => 'Setting',
- col2 => 'Value',}],
+ header => [{col1 => 'Role assigned in different domain',
+ col2 => 'Approval options'},
+ {col1 => 'Role assigned in different domain to user of type',
+ col2 => 'User information available in that domain'},
+ {col1 => "Role assigned in user's domain",
+ col2 => 'Information viewable by privileged user'},
+ {col1 => "Role assigned in user's domain",
+ col2 => 'Information viewable by unprivileged user'}],
print => \&print_privacy,
modify => \&modify_privacy,
},
@@ -520,6 +567,14 @@ sub handler {
print => \&print_ltitools,
modify => \&modify_ltitools,
},
+ 'proctoring' =>
+ {text => 'Remote Proctoring Integration',
+ help => 'Domain_Configuration_Proctoring',
+ header => [{col1 => 'Name',
+ col2 => 'Configuration'}],
+ print => \&print_proctoring,
+ modify => \&modify_proctoring,
+ },
'ssl' =>
{text => 'LON-CAPA Network (SSL)',
help => 'Domain_Configuration_Network_SSL',
@@ -625,6 +680,9 @@ END
if (grep(/^contacts$/,@actions)) {
$js .= &contacts_javascript();
}
+ if (grep(/^scantron$/,@actions)) {
+ $js .= &scantron_javascript();
+ }
&Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
} else {
# check if domconfig user exists for the domain.
@@ -747,12 +805,20 @@ sub process_changes {
$output = &modify_loadbalancing($dom,%domconfig);
} elsif ($action eq 'ltitools') {
$output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
+ } elsif ($action eq 'proctoring') {
+ $output = &modify_proctoring($r,$dom,$action,$lastactref,%domconfig);
} elsif ($action eq 'ssl') {
$output = &modify_ssl($dom,$lastactref,%domconfig);
} elsif ($action eq 'trust') {
$output = &modify_trust($dom,$lastactref,%domconfig);
} elsif ($action eq 'lti') {
$output = &modify_lti($r,$dom,$action,$lastactref,%domconfig);
+ } elsif ($action eq 'privacy') {
+ $output = &modify_privacy($dom,%domconfig);
+ } elsif ($action eq 'passwords') {
+ $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);
+ } elsif ($action eq 'wafproxy') {
+ $output = &modify_wafproxy($dom,$action,$lastactref,%domconfig);
}
return $output;
}
@@ -765,6 +831,8 @@ sub print_config_box {
$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=();
@@ -781,6 +849,14 @@ sub print_config_box {
$output =
&Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,
\@templateroles);
+ } elsif ($action eq 'ltitools') {
+ $output .= <itools_javascript($settings);
+ } elsif ($action eq 'lti') {
+ $output .= <i_javascript($settings);
+ } elsif ($action eq 'proctoring') {
+ $output .= &proctoring_javascript($settings);
+ } elsif ($action eq 'wafproxy') {
+ $output .= &wafproxy_javascript($dom);
}
$output .=
'
@@ -797,6 +873,7 @@ sub print_config_box {
if ($numheaders > 1) {
my $colspan = '';
my $rightcolspan = '';
+ my $leftnobr = '';
if (($action eq 'rolecolors') || ($action eq 'defaults') ||
($action eq 'directorysrch') ||
(($action eq 'login') && ($numheaders < 4))) {
@@ -805,12 +882,15 @@ sub print_config_box {
if ($action eq 'usersessions') {
$rightcolspan = ' colspan="3"';
}
+ if ($action eq 'passwords') {
+ $leftnobr = ' LC_nobreak';
+ }
$output .= '
- '.&mt($item->{'header'}->[0]->{'col1'}).'
+ '.&mt($item->{'header'}->[0]->{'col1'}).'
'.&mt($item->{'header'}->[0]->{'col2'}).'
';
$rowtotal ++;
@@ -818,10 +898,14 @@ sub print_config_box {
($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
- ($action eq 'contacts')) {
+ ($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'wafproxy')) {
$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') {
+ $output .= $item->{'print'}->($r,'top',$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'login') {
if ($numheaders == 4) {
$colspan = ' colspan="2"';
@@ -849,12 +933,15 @@ sub print_config_box {
if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
($action eq 'usersessions') || ($action eq 'coursecategories') ||
- ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults')) {
+ ($action eq 'trust') || ($action eq 'contacts') ||
+ ($action eq 'privacy') || ($action eq 'passwords')) {
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
$colspan = ' colspan="2"';
} elsif ($action eq 'trust') {
$output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
+ } elsif ($action eq 'passwords') {
+ $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);
} else {
$output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
}
@@ -900,6 +987,33 @@ sub print_config_box {
'."\n";
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
+ } elsif (($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'passwords')) {
+ if ($action eq 'passwords') {
+ $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal);
+ } else {
+ $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal);
+ }
+ $output .= '
+
+
+
+
+
+
+
+
+ '.&mt($item->{'header'}->[3]->{'col1'}).'
+ '.&mt($item->{'header'}->[3]->{'col2'}).' '."\n";
+ if ($action eq 'passwords') {
+ $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal);
+ } else {
+ $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+ }
+ $output .= '
+
+
+
+ ';
} else {
$output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
}
@@ -907,8 +1021,10 @@ sub print_config_box {
$rowtotal ++;
} elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
($action eq 'defaults') || ($action eq 'directorysrch') ||
- ($action eq 'helpsettings')) {
+ ($action eq 'helpsettings') || ($action eq 'wafproxy')) {
$output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+ } elsif ($action eq 'scantron') {
+ $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'ssl') {
$output .= $item->{'print'}->('connto',$dom,$settings,\$rowtotal).'
@@ -1088,10 +1204,9 @@ sub print_config_box {
$output .= &print_quotas($dom,$settings,\$rowtotal,$action);
} elsif (($action eq 'autoenroll') || ($action eq 'autocreate') ||
($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||
- ($action eq 'ltitools') || ($action eq 'lti')) {
+ ($action eq 'ltitools') || ($action eq 'lti') ||
+ ($action eq 'proctoring')) {
$output .= $item->{'print'}->($dom,$settings,\$rowtotal);
- } elsif ($action eq 'scantron') {
- $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
}
}
$output .= '
@@ -1436,7 +1551,7 @@ sub print_login {
} else {
$datatable .= ' ';
}
- $datatable .= ' ';
+ $datatable .= ' ';
}
$datatable .= '';
}
@@ -1596,7 +1711,7 @@ sub display_color_options {
my $datatable = ''.
''.$choices->{'font'}.' ';
if (!$is_custom->{'font'}) {
- $datatable .= ''.&mt('Default in use:').' '.$defaults->{'font'}.' ';
+ $datatable .= ''.&mt('Default in use:').' '.$defaults->{'font'}.' ';
} else {
$datatable .= ' ';
}
@@ -1605,12 +1720,12 @@ sub display_color_options {
$datatable .= ''.
' '.
- ' ';
+ ' ';
unless ($role eq 'login') {
$datatable .= ''.
''.$choices->{'fontmenu'}.' ';
if (!$is_custom->{'fontmenu'}) {
- $datatable .= ''.&mt('Default in use:').' '.$defaults->{'fontmenu'}.' ';
+ $datatable .= ''.&mt('Default in use:').' '.$defaults->{'fontmenu'}.' ';
} else {
$datatable .= ' ';
}
@@ -1620,7 +1735,7 @@ sub display_color_options {
' '.
- ' ';
+ ' ';
}
my $switchserver = &check_switchserver($dom,$confname);
foreach my $img (@{$images}) {
@@ -1738,7 +1853,7 @@ sub display_color_options {
my $bgs_def;
foreach my $item (@{$bgs}) {
if (!$is_custom->{$item}) {
- $bgs_def .= ''.$choices->{$item}.' '.$defaults->{'bgs'}{$item}.' ';
+ $bgs_def .= ''.$choices->{$item}.' '.$defaults->{'bgs'}{$item}.' ';
}
}
if ($bgs_def) {
@@ -1766,7 +1881,7 @@ sub display_color_options {
my $links_def;
foreach my $item (@{$links}) {
if (!$is_custom->{$item}) {
- $links_def .= ''.$choices->{$item}.''.$defaults->{'links'}{$item}.' ';
+ $links_def .= ''.$choices->{$item}.''.$defaults->{'links'}{$item}.' ';
}
}
if ($links_def) {
@@ -1852,17 +1967,15 @@ sub image_changes {
my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_;
my $output;
if ($img eq 'login') {
- # suppress image for Log-in header
+ $output = ''.$logincolors; # suppress image for Log-in header
} elsif (!$is_custom) {
if ($img ne 'domlogo') {
- $output .= &mt('Default image:').' ';
+ $output = &mt('Default image:').' ';
} else {
- $output .= &mt('Default in use:').' ';
+ $output = &mt('Default in use:').' ';
}
}
- if ($img eq 'login') { # suppress image for Log-in header
- $output .= ' '.$logincolors;
- } else {
+ if ($img ne 'login') {
if ($img_import) {
$output .= ' ';
}
@@ -1893,7 +2006,7 @@ sub print_quotas {
my $typecount = 0;
my ($css_class,%titles);
if ($context eq 'requestcourses') {
- @usertools = ('official','unofficial','community','textbook','placement');
+ @usertools = ('official','unofficial','community','textbook','placement','lti');
@options =('norequest','approval','validate','autolimit');
%validations = &Apache::lonnet::auto_courserequest_checks($dom);
%titles = &courserequest_titles();
@@ -2357,7 +2470,7 @@ sub print_studentcode {
my ($settings,$rowtotal) = @_;
my $rownum = 0;
my ($output,%current);
- my @crstypes = ('official','unofficial','community','textbook','placement');
+ my @crstypes = ('official','unofficial','community','textbook','placement','lti');
if (ref($settings) eq 'HASH') {
if (ref($settings->{'uniquecode'}) eq 'HASH') {
foreach my $type (@crstypes) {
@@ -2484,7 +2597,7 @@ sub print_textbookcourses {
$datatable .= ''.$vpos.' ';
}
$datatable .= ' '."\n".
- ' '.&mt('Add').' '."\n".
+ ' '.&mt('Add').''."\n".
''.
''.&mt('Subject:').' '."\n".
(' 'x2).
@@ -2501,13 +2614,13 @@ sub print_textbookcourses {
} else {
$datatable .= ' ';
}
+ $datatable .= ''."\n";
}
- $datatable .= ''."\n".
- ''.&mt('LON-CAPA course:').' '.
+ $datatable .= ''.&mt('LON-CAPA course:').' '.
&Apache::loncommon::select_dom_form($env{'request.role.domain'},$type.'_addbook_cdom').
' '.
&Apache::loncommon::selectcourse_link
- ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course');
+ ('display',$type.'_addbook_cnum',$type.'_addbook_cdom',undef,undef,undef,'Course').
' '."\n".
''."\n";
$itemcount ++;
@@ -2712,6 +2825,134 @@ function toggleLTITools(form,setting,ite
}
}
}
+ if (setting == 'user') {
+ divid = 'ltitools_'+setting+'_div_'+item;
+ var checkid = 'ltitools_'+setting+'_field_'+item;
+ if (document.getElementById(divid)) {
+ if (document.getElementById(checkid)) {
+ if (document.getElementById(checkid).checked) {
+ document.getElementById(divid).style.display = 'inline-block';
+ } else {
+ document.getElementById(divid).style.display = 'none';
+ }
+ }
+ }
+ }
+ return;
+}
+// ]]>
+
+
+ENDSCRIPT
+}
+
+sub wafproxy_javascript {
+ my ($dom) = @_;
+ return <<"ENDSCRIPT";
+
+
+ENDSCRIPT
+}
+
+
sub lti_javascript {
my ($settings) = @_;
my $togglejs = <i_toggle_js();
@@ -2793,32 +3130,76 @@ ENDSCRIPT
}
sub lti_toggle_js {
+ my %lcauthparmtext = &Apache::lonlocal::texthash (
+ localauth => 'Local auth argument',
+ krb => 'Kerberos domain',
+ );
return <<"ENDSCRIPT";
+
+ENDSCRIPT
+
+}
+
sub print_scantronformat {
my ($r,$dom,$confname,$settings,$rowtotal) = @_;
my $itemcount = 1;
@@ -7528,8 +9799,8 @@ sub print_scantronformat {
if ($configuserok eq 'ok') {
if ($author_ok eq 'ok') {
my %legacyfile = (
- default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',
- custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',
+ default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',
+ custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',
);
my %md5chk;
foreach my $type (keys(%legacyfile)) {
@@ -7538,7 +9809,7 @@ sub print_scantronformat {
}
if ($md5chk{'default'} ne $md5chk{'custom'}) {
foreach my $type (keys(%legacyfile)) {
- ($scantronurls{$type},my $error) =
+ ($scantronurls{$type},my $error) =
&legacy_scantronformat($r,$dom,$confname,
$type,$legacyfile{$type},
$scantronurls{$type},
@@ -7549,13 +9820,13 @@ sub print_scantronformat {
}
if (keys(%error) == 0) {
$is_custom = 1;
- $confhash{'scantron'}{'scantronformat'} =
+ $confhash{'scantron'}{'scantronformat'} =
$scantronurls{'custom'};
- my $putresult =
+ my $putresult =
&Apache::lonnet::put_dom('configuration',
\%confhash,$dom);
if ($putresult ne 'ok') {
- $error{'custom'} =
+ $error{'custom'} =
''.
&mt('An error occurred updating the domain configuration: [_1]',$putresult).' ';
}
@@ -7675,6 +9946,129 @@ sub legacy_scantronformat {
return ($url,$error);
}
+sub print_scantronconfig {
+ my ($dom,$settings,$rowtotal) = @_;
+ my $itemcount = 2;
+ my $is_checked = ' checked="checked"';
+ my %optionson = (
+ hdr => ' checked="checked"',
+ pad => ' checked="checked"',
+ rem => ' checked="checked"',
+ );
+ my %optionsoff = (
+ hdr => '',
+ pad => '',
+ rem => '',
+ );
+ my $currcsvsty = 'none';
+ my ($datatable,%csvfields,%checked,%onclick,%csvoptions);
+ my @fields = &scantroncsv_fields();
+ my %titles = &scantronconfig_titles();
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{config}) eq 'HASH') {
+ if ($settings->{config}->{dat}) {
+ $checked{'dat'} = $is_checked;
+ }
+ if (ref($settings->{config}->{csv}) eq 'HASH') {
+ if (ref($settings->{config}->{csv}->{fields}) eq 'HASH') {
+ %csvfields = %{$settings->{config}->{csv}->{fields}};
+ if (keys(%csvfields) > 0) {
+ $checked{'csv'} = $is_checked;
+ $currcsvsty = 'block';
+ }
+ }
+ if (ref($settings->{config}->{csv}->{options}) eq 'HASH') {
+ %csvoptions = %{$settings->{config}->{csv}->{options}};
+ foreach my $option (keys(%optionson)) {
+ unless ($csvoptions{$option}) {
+ $optionsoff{$option} = $optionson{$option};
+ $optionson{$option} = '';
+ }
+ }
+ }
+ }
+ } else {
+ $checked{'dat'} = $is_checked;
+ }
+ } else {
+ $checked{'dat'} = $is_checked;
+ }
+ $onclick{'csv'} = ' onclick="toggleScantron(this.form);"';
+ my $css_class = $itemcount%2? ' class="LC_odd_row"':'';
+ $datatable = ''.&mt('Supported formats').' '.
+ '';
+ foreach my $item ('dat','csv') {
+ my $id;
+ if ($item eq 'csv') {
+ $id = 'id="scantronconfcsv" ';
+ }
+ $datatable .= ' '.
+ $titles{$item}.' '.(' 'x3);
+ if ($item eq 'csv') {
+ $datatable .= ''.
+ ''.&mt('CSV Column Mapping').' '.
+ ''.&mt('Field').' '.&mt('Location').' '."\n";
+ foreach my $col (@fields) {
+ my $selnone;
+ if ($csvfields{$col} eq '') {
+ $selnone = ' selected="selected"';
+ }
+ $datatable .= ''.$titles{$col}.' '.
+ ''.
+ ' ';
+ for (my $i=0; $i<20; $i++) {
+ my $shown = $i+1;
+ my $sel;
+ unless ($selnone) {
+ if (exists($csvfields{$col})) {
+ if ($csvfields{$col} == $i) {
+ $sel = ' selected="selected"';
+ }
+ }
+ }
+ $datatable .= ''.$shown.' ';
+ }
+ $datatable .= ' ';
+ }
+ $datatable .= '
'.
+ ''.
+ ''.&mt('CSV Options').' ';
+ foreach my $option ('hdr','pad','rem') {
+ $datatable .= ''.$titles{$option}.':'.
+ ' '.
+ &mt('Yes').' '.(' 'x2)."\n".
+ ' '.&mt('No').' ';
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ }
+ }
+ $datatable .= ' ';
+ $$rowtotal ++;
+ return $datatable;
+}
+
+sub scantronconfig_titles {
+ return &Apache::lonlocal::texthash(
+ dat => 'Standard format (.dat)',
+ csv => 'Comma separated values (.csv)',
+ hdr => 'Remove first line in file (contains column titles)',
+ pad => 'Prepend 0s to PaperID',
+ rem => 'Remove leading spaces (except Question Response columns)',
+ CODE => 'CODE',
+ ID => 'Student ID',
+ PaperID => 'Paper ID',
+ FirstName => 'First Name',
+ LastName => 'Last Name',
+ FirstQuestion => 'First Question Response',
+ Section => 'Section',
+ );
+}
+
+sub scantroncsv_fields {
+ return ('PaperID','LastName','FirstName','ID','Section','CODE','FirstQuestion');
+}
+
sub print_coursecategories {
my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
my $datatable;
@@ -7717,7 +10111,7 @@ sub print_coursecategories {
' '.$lt{$type}.' ';
}
- $datatable .= '';
+ $datatable .= '';
$itemcount ++;
}
$$rowtotal += $itemcount;
@@ -7803,7 +10197,7 @@ sub print_coursecategories {
$can_catcomm_dom.' value="dom" />'.$level{'dom'}.' '.
' '.$level{'comm'}.' '.
- ''.
+ ' '.
''.$title{'togglecatsplace'}.' '.
''.
' {'header'}->[1]->{'col2'}.' '
+ $datatable .= ' '.$hdritem->{'header'}->[1]->{'col2'}.' '
.&initialize_categories($itemcount);
}
$$rowtotal += $itemcount;
@@ -8008,7 +10402,7 @@ sub print_serverstatuses {
''.
' '.
- ''."\n";
+ ' '."\n";
}
$$rowtotal += $rownum;
return $datatable;
@@ -8023,35 +10417,7 @@ sub serverstatus_pages {
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 '') {
@@ -8105,15 +10471,100 @@ $jstext
return;
}
-$intauthjs
-
// ]]>
ENDSCRIPT
+ }
+ return;
+}
+
+sub passwords_javascript {
+ my %intalert = &Apache::lonlocal::texthash (
+ authcheck => '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.',
+ authcost => 'Warning: bcrypt encryption cost for internal authentication must be an integer.',
+ passmin => 'Warning: minimum password length must be a positive integer greater than 6.',
+ passmax => 'Warning: maximum password length must be a positive integer (or blank).',
+ passexp => 'Warning: days before password expiration must be a positive integer (or blank).',
+ passnum => 'Warning: number of previous passwords to save must be a positive integer (or blank).',
+ );
+ &js_escape(\%intalert);
+ my $defmin = $Apache::lonnet::passwdmin;
+ my $intauthjs = <<"ENDSCRIPT";
+
+function warnIntAuth(field) {
+ if (field.name == 'intauth_check') {
+ if (field.value == '2') {
+ alert('$intalert{authcheck}');
+ }
+ }
+ if (field.name == 'intauth_cost') {
+ field.value.replace(/\s/g,'');
+ if (field.value != '') {
+ var regexdigit=/^\\d+\$/;
+ if (!regexdigit.test(field.value)) {
+ alert('$intalert{authcost}');
+ }
+ }
+ }
+ return;
+}
+
+function warnIntPass(field) {
+ field.value.replace(/^\s+/,'');
+ field.value.replace(/\s+\$/,'');
+ var regexdigit=/^\\d+\$/;
+ if (field.name == 'passwords_min') {
+ if (field.value == '') {
+ alert('$intalert{passmin}');
+ field.value = '$defmin';
+ } else {
+ if (!regexdigit.test(field.value)) {
+ alert('$intalert{passmin}');
+ field.value = '$defmin';
+ }
+ var minval = parseInt(field.value,10);
+ if (minval < $defmin) {
+ alert('$intalert{passmin}');
+ field.value = '$defmin';
+ }
+ }
} else {
- return &Apache::lonhtmlcommon::scripttag($intauthjs);
+ if (field.value == '0') {
+ field.value = '';
+ }
+ if (field.value != '') {
+ if (field.name == 'passwords_expire') {
+ var regexpposnum=/^\\d+(|\\.\\d*)\$/;
+ if (!regexpposnum.test(field.value)) {
+ alert('$intalert{passexp}');
+ field.value = '';
+ } else {
+ var expval = parseFloat(field.value);
+ if (expval == 0) {
+ alert('$intalert{passexp}');
+ field.value = '';
+ }
+ }
+ } else {
+ if (!regexdigit.test(field.value)) {
+ if (field.name == 'passwords_max') {
+ alert('$intalert{passmax}');
+ } else {
+ if (field.name == 'passwords_numsaved') {
+ alert('$intalert{passnum}');
+ }
+ }
+ field.value = '';
+ }
+ }
+ }
}
+ return;
+}
+
+ENDSCRIPT
+ return &Apache::lonhtmlcommon::scripttag($intauthjs);
}
sub coursecategories_javascript {
@@ -8231,25 +10682,28 @@ ENDSCRIPT
sub initialize_categories {
my ($itemcount) = @_;
my ($datatable,$css_class,$chgstr);
- my %default_names = (
+ my %default_names = &Apache::lonlocal::texthash (
instcode => 'Official courses (with institutional codes)',
communities => 'Communities',
placement => 'Placement Tests',
);
- my $select0 = ' selected="selected"';
- my $select1 = '';
+ my %selnum = (
+ instcode => '0',
+ communities => '1',
+ placement => '2',
+ );
+ my %selected;
foreach my $default ('instcode','communities','placement') {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
- $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"';
- if (($default eq 'communities') || ($default eq 'placement')) {
- $select1 = $select0;
- $select0 = '';
- }
+ $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','0'".');"';
+ map { $selected{$selnum{$_}} = '' } keys(%selnum);
+ $selected{$selnum{$default}} = ' selected="selected"';
$datatable .= ''
- .''
- .'1 '
- .'2 '
- .'3 '
+ .''
+ .'1 '
+ .'2 '
+ .'3 '
+ .'4 '
.$default_names{$default}
.' '
.' '
@@ -8264,9 +10718,11 @@ sub initialize_categories {
.''
.'1 '
.'2 '
- .'3 '
- .&mt('Add category').' '.&mt('Name:')
- .' ';
+ .'3 '
+ .'4 '
+ .&mt('Add category').''.&mt('Name:')
+ .' '
+ .' ';
return $datatable;
}
@@ -8321,7 +10777,7 @@ sub build_category_rows {
pop(@{$path});
}
} else {
- $text .= &mt('Add subcategory:').' '.&mt('Add subcategory:').' ';
+ $text .= ''.&mt('Add subcategory:').' ';
}
}
}
@@ -8354,7 +10810,7 @@ sub build_category_rows {
sub modifiable_userdata_row {
my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref,
- $rowid,$customcss,$rowstyle) = @_;
+ $rowid,$customcss,$rowstyle,$itemdesc) = @_;
my ($role,$rolename,$statustype);
$role = $item;
if ($context eq 'cancreate') {
@@ -8375,6 +10831,10 @@ sub modifiable_userdata_row {
} else {
$rolename = $role;
}
+ } elsif ($context eq 'lti') {
+ $rolename = &mt('Institutional data used (if available)');
+ } elsif ($context eq 'privacy') {
+ $rolename = $itemdesc;
} else {
if ($role eq 'cr') {
$rolename = &mt('Custom role');
@@ -8417,30 +10877,39 @@ sub modifiable_userdata_row {
'';
my $rem;
my %checks;
+ my %current;
if (ref($settings) eq 'HASH') {
- if (ref($settings->{$context}) eq 'HASH') {
+ my $hashref;
+ if ($context eq 'lti') {
+ if (ref($settings) eq 'HASH') {
+ $hashref = $settings->{'instdata'};
+ }
+ } elsif ($context eq 'privacy') {
+ my ($key,$inner) = split(/_/,$role);
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{$key}) eq 'HASH') {
+ $hashref = $settings->{$key}->{$inner};
+ }
+ }
+ } elsif (ref($settings->{$context}) eq 'HASH') {
if (ref($settings->{$context}->{$role}) eq 'HASH') {
- my $hashref = $settings->{$context}->{$role};
- if ($role eq 'emailusername') {
- if ($statustype) {
- if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
- $hashref = $settings->{$context}->{$role}->{$statustype};
- if (ref($hashref) eq 'HASH') {
- foreach my $field (@fields) {
- if ($hashref->{$field}) {
- $checks{$field} = $hashref->{$field};
- }
- }
- }
- }
+ $hashref = $settings->{'lti_instdata'};
+ }
+ if ($role eq 'emailusername') {
+ if ($statustype) {
+ if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
+ $hashref = $settings->{$context}->{$role}->{$statustype};
}
- } else {
- if (ref($hashref) eq 'HASH') {
- foreach my $field (@fields) {
- if ($hashref->{$field}) {
- $checks{$field} = ' checked="checked" ';
- }
- }
+ }
+ }
+ }
+ if (ref($hashref) eq 'HASH') {
+ foreach my $field (@fields) {
+ if ($hashref->{$field}) {
+ if ($role eq 'emailusername') {
+ $checks{$field} = $hashref->{$field};
+ } else {
+ $checks{$field} = ' checked="checked" ';
}
}
}
@@ -8459,8 +10928,26 @@ sub modifiable_userdata_row {
my $check = ' ';
unless ($role eq 'emailusername') {
if (exists($checks{$fields[$i]})) {
- $check = $checks{$fields[$i]}
- } else {
+ $check = $checks{$fields[$i]};
+ } elsif ($context eq 'privacy') {
+ if ($role =~ /^priv_(domain|course)$/) {
+ if (ref($settings) ne 'HASH') {
+ $check = ' checked="checked" ';
+ }
+ } elsif ($role =~ /^priv_(author|community)$/) {
+ if (ref($settings) ne 'HASH') {
+ unless ($fields[$i] eq 'id') {
+ $check = ' checked="checked" ';
+ }
+ }
+ } elsif ($role =~ /^(unpriv|othdom)_/) {
+ if (ref($settings) ne 'HASH') {
+ if (($fields[$i] eq 'lastname') || ($fields[$i] eq 'firstname')) {
+ $check = ' checked="checked" ';
+ }
+ }
+ }
+ } elsif ($context ne 'lti') {
if ($role eq 'st') {
if (ref($settings) ne 'HASH') {
$check = ' checked="checked" ';
@@ -8470,6 +10957,7 @@ sub modifiable_userdata_row {
}
$output .= ''.
'';
+ my $prefix = 'canmodify';
if ($role eq 'emailusername') {
unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {
$checks{$fields[$i]} = 'omit';
@@ -8480,13 +10968,18 @@ sub modifiable_userdata_row {
$checked='checked="checked" ';
}
$output .= ''.
- ' '.
+ ' '.
&mt($option).' '.(' ' x2);
}
$output .= ''.$fieldtitles{$fields[$i]}.' ';
} else {
+ if ($context eq 'lti') {
+ $prefix = 'lti';
+ } elsif ($context eq 'privacy') {
+ $prefix = 'privacy';
+ }
$output .= ''.
- ' '.$fieldtitles{$fields[$i]}.
' ';
}
@@ -8588,7 +11081,7 @@ sub insttypes_row {
}
$output .= ' ';
} else {
- if (($rem == 0) && (@{$types} > 0)) {
+ if ($rem == 0) {
$output .= '';
}
if ($colsleft > 1) {
@@ -9571,7 +12064,7 @@ sub check_configuser {
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);
@@ -9896,7 +12389,7 @@ sub modify_quotas {
$context = $action;
}
if ($context eq 'requestcourses') {
- @usertools = ('official','unofficial','community','textbook','placement');
+ @usertools = ('official','unofficial','community','textbook','placement','lti');
@options =('norequest','approval','validate','autolimit');
%validations = &Apache::lonnet::auto_courserequest_checks($dom);
%titles = &courserequest_titles();
@@ -9945,7 +12438,7 @@ sub modify_quotas {
my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
@approvalnotify = sort(@approvalnotify);
$confhash{'notify'}{'approval'} = join(',',@approvalnotify);
- my @crstypes = ('official','unofficial','community','textbook','placement');
+ my @crstypes = ('official','unofficial','community','textbook','placement','lti');
my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
foreach my $type (@hasuniquecode) {
if (grep(/^\Q$type\E$/,@crstypes)) {
@@ -10644,8 +13137,11 @@ sub modify_ltitools {
$allpos[$position] = $newid;
}
$changes{$newid} = 1;
- foreach my $item ('title','url','key','secret') {
+ foreach my $item ('title','url','key','secret','lifetime') {
$env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;
+ if ($item eq 'lifetime') {
+ $env{'form.ltitools_add_'.$item} =~ s/[^\d.]//g;
+ }
if ($env{'form.ltitools_add_'.$item}) {
if (($item eq 'key') || ($item eq 'secret')) {
$encconfig{$newid}{$item} = $env{'form.ltitools_add_'.$item};
@@ -10660,6 +13156,11 @@ sub modify_ltitools {
if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {
$confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};
}
+ if ($env{'form.ltitools_add_sigmethod'} eq 'HMAC-SHA256') {
+ $confhash{$newid}{'sigmethod'} = $env{'form.ltitools_add_sigmethod'};
+ } else {
+ $confhash{$newid}{'sigmethod'} = 'HMAC-SHA1';
+ }
foreach my $item ('width','height','linktext','explanation') {
$env{'form.ltitools_add_'.$item} =~ s/^\s+//;
$env{'form.ltitools_add_'.$item} =~ s/\s+$//;
@@ -10722,6 +13223,13 @@ sub modify_ltitools {
}
}
}
+ if (ref($confhash{$newid}{'fields'}) eq 'HASH') {
+ if ($confhash{$newid}{'fields'}{'user'}) {
+ if ($env{'form.ltitools_userincdom_add'}) {
+ $confhash{$newid}{'incdom'} = 1;
+ }
+ }
+ }
my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig');
foreach my $item (@courseconfig) {
$confhash{$newid}{'crsconf'}{$item} = 1;
@@ -10768,7 +13276,7 @@ sub modify_ltitools {
} else {
my $newpos = $env{'form.ltitools_'.$itemid};
$newpos =~ s/\D+//g;
- foreach my $item ('title','url') {
+ foreach my $item ('title','url','lifetime') {
$confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
$changes{$itemid} = 1;
@@ -10786,6 +13294,18 @@ sub modify_ltitools {
if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {
$confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};
}
+ if ($env{'form.ltitools_sigmethod_'.$i} eq 'HMAC-SHA256') {
+ $confhash{$itemid}{'sigmethod'} = $env{'form.ltitools_sigmethod_'.$i};
+ } else {
+ $confhash{$itemid}{'sigmethod'} = 'HMAC-SHA1';
+ }
+ if ($domconfig{$action}{$itemid}{'sigmethod'} eq '') {
+ if ($confhash{$itemid}{'sigmethod'} ne 'HMAC-SHA1') {
+ $changes{$itemid} = 1;
+ }
+ } elsif ($domconfig{$action}{$itemid}{'sigmethod'} ne $confhash{$itemid}{'sigmethod'}) {
+ $changes{$itemid} = 1;
+ }
foreach my $size ('width','height') {
$env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;
$env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;
@@ -10840,7 +13360,7 @@ sub modify_ltitools {
if ($env{'form.ltitools_'.$extra.'_'.$i}) {
$confhash{$itemid}{$extra} = 1;
if ($env{'form.ltitools_'.$extra.'valid_'.$i} ne '') {
- my $lifetime = $env{'form.ltitools_'.$extra.'valid_add'};
+ my $lifetime = $env{'form.ltitools_'.$extra.'valid_'.$i};
$lifetime =~ s/^\s+|\s+$//g;
if ($lifetime =~ /^\d+\.?\d*$/) {
$confhash{$itemid}{$extra.'valid'} = $lifetime;
@@ -10899,6 +13419,16 @@ sub modify_ltitools {
}
}
}
+ if (ref($confhash{$itemid}{'fields'}) eq 'HASH') {
+ if ($confhash{$itemid}{'fields'}{'user'}) {
+ if ($env{'form.ltitools_userincdom_'.$i}) {
+ $confhash{$itemid}{'incdom'} = 1;
+ }
+ if ($domconfig{$action}{$itemid}{'incdom'} ne $confhash{$itemid}{'incdom'}) {
+ $changes{$itemid} = 1;
+ }
+ }
+ }
$allpos[$newpos] = $itemid;
}
if ($imgdeletions{$itemid}) {
@@ -11032,7 +13562,7 @@ sub modify_ltitools {
$resulttext .= '';
my $position = $pos + 1;
$resulttext .= ''.&mt('Order: [_1]',$position).' ';
- foreach my $item ('version','msgtype','url') {
+ foreach my $item ('version','msgtype','sigmethod','url','lifetime') {
if ($confhash{$itemid}{$item} ne '') {
$resulttext .= ''.$lt{$item}.': '.$confhash{$itemid}{$item}.' ';
}
@@ -11057,7 +13587,7 @@ sub modify_ltitools {
}
}
if (!$numconfig) {
- $resulttext .= &mt('None');
+ $resulttext .= ' '.&mt('None');
}
$resulttext .= '';
foreach my $item ('passback','roster') {
@@ -11109,6 +13639,13 @@ sub modify_ltitools {
}
if ($fieldlist) {
$fieldlist =~ s/,$//;
+ if ($confhash{$itemid}{'fields'}{'user'}) {
+ if ($confhash{$itemid}{'incdom'}) {
+ $fieldlist .= ' ('.&mt('username:domain').')';
+ } else {
+ $fieldlist .= ' ('.&mt('username').')';
+ }
+ }
$resulttext .= ''.&mt('Data sent').':'.$fieldlist.' ';
}
}
@@ -11229,6 +13766,536 @@ sub get_ltitools_id {
return ($id,$error);
}
+sub modify_proctoring {
+ my ($r,$dom,$action,$lastactref,%domconfig) = @_;
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+ my (@allpos,%changes,%confhash,%encconfhash,$errors,$resulttext,%imgdeletions);
+ my $confname = $dom.'-domainconfig';
+ my $servadm = $r->dir_config('lonAdmEMail');
+ my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
+ my %providernames = &proctoring_providernames();
+ my $maxnum = scalar(keys(%providernames));
+
+ my (%requserfields,%optuserfields,%defaults,%extended,%crsconf,@courseroles,@ltiroles);
+ my ($requref,$opturef,$defref,$extref,$crsref,$rolesref,$ltiref) = &proctoring_data();
+ if (ref($requref) eq 'HASH') {
+ %requserfields = %{$requref};
+ }
+ if (ref($opturef) eq 'HASH') {
+ %optuserfields = %{$opturef};
+ }
+ if (ref($defref) eq 'HASH') {
+ %defaults = %{$defref};
+ }
+ if (ref($extref) eq 'HASH') {
+ %extended = %{$extref};
+ }
+ if (ref($crsref) eq 'HASH') {
+ %crsconf = %{$crsref};
+ }
+ if (ref($rolesref) eq 'ARRAY') {
+ @courseroles = @{$rolesref};
+ }
+ if (ref($ltiref) eq 'ARRAY') {
+ @ltiroles = @{$ltiref};
+ }
+
+ if (ref($domconfig{$action}) eq 'HASH') {
+ my @todeleteimages = &Apache::loncommon::get_env_multiple('form.proctoring_image_del');
+ if (@todeleteimages) {
+ map { $imgdeletions{$_} = 1; } @todeleteimages;
+ }
+ }
+ my %customadds;
+ my @newcustom = &Apache::loncommon::get_env_multiple('form.proctoring_customadd');
+ if (@newcustom) {
+ map { $customadds{$_} = 1; } @newcustom;
+ }
+ foreach my $provider (sort(keys(%providernames))) {
+ $confhash{$provider} = {};
+ my $pos = $env{'form.proctoring_pos_'.$provider};
+ $pos =~ s/\D+//g;
+ $allpos[$pos] = $provider;
+ my (%current,%currentenc);
+ my $showroles = 0;
+ if (ref($domconfig{$action}) eq 'HASH') {
+ if (ref($domconfig{$action}{$provider}) eq 'HASH') {
+ %current = %{$domconfig{$action}{$provider}};
+ foreach my $item ('key','secret') {
+ $currentenc{$item} = $current{$item};
+ delete($current{$item});
+ }
+ }
+ }
+ if ($env{'form.proctoring_available_'.$provider}) {
+ $confhash{$provider}{'available'} = 1;
+ unless ($current{'available'}) {
+ $changes{$provider} = 1;
+ }
+ } else {
+ %{$confhash{$provider}} = %current;
+ %{$encconfhash{$provider}} = %currentenc;
+ $confhash{$provider}{'available'} = 0;
+ if ($current{'available'}) {
+ $changes{$provider} = 1;
+ }
+ }
+ if ($confhash{$provider}{'available'}) {
+ foreach my $field ('lifetime','version','sigmethod','url','key','secret') {
+ my $possval = $env{'form.proctoring_'.$provider.'_'.$field};
+ if ($field eq 'lifetime') {
+ if ($possval =~ /^\d+$/) {
+ $confhash{$provider}{$field} = $possval;
+ }
+ } elsif ($field eq 'version') {
+ if ($possval =~ /^\d+\.\d+$/) {
+ $confhash{$provider}{$field} = $possval;
+ }
+ } elsif ($field eq 'sigmethod') {
+ if ($possval =~ /^\QHMAC-SHA\E(1|256)$/) {
+ $confhash{$provider}{$field} = $possval;
+ }
+ } elsif ($field eq 'url') {
+ $confhash{$provider}{$field} = $possval;
+ } elsif (($field eq 'key') || ($field eq 'secret')) {
+ $encconfhash{$provider}{$field} = $possval;
+ unless ($currentenc{$field} eq $possval) {
+ $changes{$provider} = 1;
+ }
+ }
+ unless (($field eq 'key') || ($field eq 'secret')) {
+ unless ($current{$field} eq $confhash{$provider}{$field}) {
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ if ($imgdeletions{$provider}) {
+ $changes{$provider} = 1;
+ } elsif ($env{'form.proctoring_image_'.$provider.'.filename'} ne '') {
+ my ($imageurl,$error) =
+ &process_proctoring_image($r,$dom,$confname,'proctoring_image_'.$provider,$provider,
+ $configuserok,$switchserver,$author_ok);
+ if ($imageurl) {
+ $confhash{$provider}{'image'} = $imageurl;
+ $changes{$provider} = 1;
+ }
+ if ($error) {
+ &Apache::lonnet::logthis($error);
+ $errors .= ''.$error.' ';
+ }
+ } elsif (exists($current{'image'})) {
+ $confhash{$provider}{'image'} = $current{'image'};
+ }
+ if (ref($requserfields{$provider}) eq 'ARRAY') {
+ if (@{$requserfields{$provider}} > 0) {
+ if (grep(/^user$/,@{$requserfields{$provider}})) {
+ if ($env{'form.proctoring_userincdom_'.$provider}) {
+ $confhash{$provider}{'incdom'} = 1;
+ }
+ unless ($current{'incdom'} eq $confhash{$provider}{'incdom'}) {
+ $changes{$provider} = 1;
+ }
+ }
+ if (grep(/^roles$/,@{$requserfields{$provider}})) {
+ $showroles = 1;
+ }
+ }
+ }
+ $confhash{$provider}{'fields'} = [];
+ if (ref($optuserfields{$provider}) eq 'ARRAY') {
+ if (@{$optuserfields{$provider}} > 0) {
+ my @optfields = &Apache::loncommon::get_env_multiple('form.proctoring_optional_'.$provider);
+ foreach my $field (@{$optuserfields{$provider}}) {
+ if (grep(/^\Q$field\E$/,@optfields)) {
+ push(@{$confhash{$provider}{'fields'}},$field);
+ }
+ }
+ }
+ if (ref($current{'fields'}) eq 'ARRAY') {
+ unless ($changes{$provider}) {
+ my @new = sort(@{$confhash{$provider}{'fields'}});
+ my @old = sort(@{$current{'fields'}});
+ my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
+ if (@diffs) {
+ $changes{$provider} = 1;
+ }
+ }
+ } elsif (@{$confhash{$provider}{'fields'}}) {
+ $changes{$provider} = 1;
+ }
+ }
+ if (ref($defaults{$provider}) eq 'ARRAY') {
+ if (@{$defaults{$provider}} > 0) {
+ my %options;
+ if (ref($extended{$provider}) eq 'HASH') {
+ %options = %{$extended{$provider}};
+ }
+ my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_defaults_'.$provider);
+ foreach my $field (@{$defaults{$provider}}) {
+ if ((exists($options{$field})) && (ref($options{$field}) eq 'ARRAY')) {
+ my $poss = $env{'form.proctoring_defaults_'.$field.'_'.$provider};
+ if (grep(/^\Q$poss\E$/,@{$options{$field}})) {
+ push(@{$confhash{$provider}{'defaults'}},$poss);
+ }
+ } elsif ((exists($options{$field})) && (ref($options{$field}) eq 'HASH')) {
+ foreach my $inner (keys(%{$options{$field}})) {
+ if (ref($options{$field}{$inner}) eq 'ARRAY') {
+ my $poss = $env{'form.proctoring_'.$inner.'_'.$provider};
+ if (grep(/^\Q$poss\E$/,@{$options{$field}{$inner}})) {
+ $confhash{$provider}{'defaults'}{$inner} = $poss;
+ }
+ } else {
+ $confhash{$provider}{'defaults'}{$inner} = $env{'form.proctoring_'.$inner.'_'.$provider};
+ }
+ }
+ } else {
+ if (grep(/^\Q$field\E$/,@checked)) {
+ push(@{$confhash{$provider}{'defaults'}},$field);
+ }
+ }
+ }
+ if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') {
+ if (ref($current{'defaults'}) eq 'ARRAY') {
+ unless ($changes{$provider}) {
+ my @new = sort(@{$confhash{$provider}{'defaults'}});
+ my @old = sort(@{$current{'defaults'}});
+ my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
+ if (@diffs) {
+ $changes{$provider} = 1;
+ }
+ }
+ } elsif (ref($current{'defaults'}) eq 'ARRAY') {
+ if (@{$current{'defaults'}}) {
+ $changes{$provider} = 1;
+ }
+ }
+ } elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') {
+ if (ref($current{'defaults'}) eq 'HASH') {
+ unless ($changes{$provider}) {
+ foreach my $key (keys(%{$confhash{$provider}{'defaults'}})) {
+ unless ($confhash{$provider}{'defaults'}{$key} eq $current{'defaults'}{$key}) {
+ $changes{$provider} = 1;
+ last;
+ }
+ }
+ }
+ unless ($changes{$provider}) {
+ foreach my $key (keys(%{$current{'defaults'}})) {
+ unless ($current{'defaults'}{$key} eq $confhash{$provider}{'defaults'}{$key}) {
+ $changes{$provider} = 1;
+ last;
+ }
+ }
+ }
+ } elsif (keys(%{$confhash{$provider}{'defaults'}})) {
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ }
+ if (ref($crsconf{$provider}) eq 'ARRAY') {
+ if (@{$crsconf{$provider}} > 0) {
+ $confhash{$provider}{'crsconf'} = [];
+ my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_crsconf_'.$provider);
+ foreach my $crsfield (@{$crsconf{$provider}}) {
+ if (grep(/^\Q$crsfield\E$/,@checked)) {
+ push(@{$confhash{$provider}{'crsconf'}},$crsfield);
+ }
+ }
+ if (ref($current{'crsconf'}) eq 'ARRAY') {
+ unless ($changes{$provider}) {
+ my @new = sort(@{$confhash{$provider}{'crsconf'}});
+ my @old = sort(@{$current{'crsconf'}});
+ my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old);
+ if (@diffs) {
+ $changes{$provider} = 1;
+ }
+ }
+ } elsif (@{$confhash{$provider}{'crsconf'}}) {
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ if ($showroles) {
+ $confhash{$provider}{'roles'} = {};
+ foreach my $role (@courseroles) {
+ my $poss = $env{'form.proctoring_roles_'.$role.'_'.$provider};
+ if (grep(/^\Q$poss\E$/,@ltiroles)) {
+ $confhash{$provider}{'roles'}{$role} = $poss;
+ }
+ }
+ unless ($changes{$provider}) {
+ if (ref($current{'roles'}) eq 'HASH') {
+ foreach my $role (keys(%{$current{'roles'}})) {
+ unless ($current{'roles'}{$role} eq $confhash{$provider}{'roles'}{$role}) {
+ $changes{$provider} = 1;
+ last
+ }
+ }
+ unless ($changes{$provider}) {
+ foreach my $role (keys(%{$confhash{$provider}{'roles'}})) {
+ unless ($confhash{$provider}{'roles'}{$role} eq $current{'roles'}{$role}) {
+ $changes{$provider} = 1;
+ last;
+ }
+ }
+ }
+ } elsif (keys(%{$confhash{$provider}{'roles'}})) {
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ if (ref($current{'custom'}) eq 'HASH') {
+ my @customdels = &Apache::loncommon::get_env_multiple('form.proctoring_customdel_'.$provider);
+ foreach my $key (keys(%{$current{'custom'}})) {
+ if (grep(/^\Q$key\E$/,@customdels)) {
+ $changes{$provider} = 1;
+ } else {
+ $confhash{$provider}{'custom'}{$key} = $env{'form.proctoring_customval_'.$key.'_'.$provider};
+ if ($confhash{$provider}{'custom'}{$key} ne $current{'custom'}{$key}) {
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ }
+ if ($customadds{$provider}) {
+ my $name = $env{'form.proctoring_custom_name_'.$provider};
+ $name =~ s/(`)/'/g;
+ $name =~ s/^\s+//;
+ $name =~ s/\s+$//;
+ my $value = $env{'form.proctoring_custom_value_'.$provider};
+ $value =~ s/(`)/'/g;
+ $value =~ s/^\s+//;
+ $value =~ s/\s+$//;
+ if ($name ne '') {
+ $confhash{$provider}{'custom'}{$name} = $value;
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ }
+ if (@allpos > 0) {
+ my $idx = 0;
+ foreach my $provider (@allpos) {
+ if ($provider ne '') {
+ $confhash{$provider}{'order'} = $idx;
+ unless ($changes{$provider}) {
+ if (ref($domconfig{$action}) eq 'HASH') {
+ if (ref($domconfig{$action}{$provider}) eq 'HASH') {
+ if ($domconfig{$action}{$provider}{'order'} ne $idx) {
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ }
+ $idx ++;
+ }
+ }
+ }
+ my %proc_hash = (
+ $action => { %confhash }
+ );
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%proc_hash,
+ $dom);
+ if ($putresult eq 'ok') {
+ my %proc_enchash = (
+ $action => { %encconfhash }
+ );
+ &Apache::lonnet::put_dom('encconfig',\%proc_enchash,$dom);
+ if (keys(%changes) > 0) {
+ my $cachetime = 24*60*60;
+ my %procall = %confhash;
+ foreach my $provider (keys(%procall)) {
+ if (ref($encconfhash{$provider}) eq 'HASH') {
+ foreach my $key ('key','secret') {
+ $procall{$provider}{$key} = $encconfhash{$provider}{$key};
+ }
+ }
+ }
+ &Apache::lonnet::do_cache_new('proctoring',$dom,\%procall,$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'proctoring'} = 1;
+ }
+ $resulttext = &mt('Configuration for Provider(s) with changes:').'';
+ my %bynum;
+ foreach my $provider (sort(keys(%changes))) {
+ my $position = $confhash{$provider}{'order'};
+ $bynum{$position} = $provider;
+ }
+ foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
+ my $provider = $bynum{$pos};
+ my %lt = &proctoring_titles($provider);
+ my %fieldtitles = &proctoring_fieldtitles($provider);
+ if (!$confhash{$provider}{'available'}) {
+ $resulttext .= ''.&mt('Proctoring integration unavailable for: [_1]',''.$providernames{$provider}.' ').' ';
+ } else {
+ $resulttext .= ''.&mt('Proctoring integration available for: [_1]',''.$providernames{$provider}.' ');
+ if ($confhash{$provider}{'image'}) {
+ $resulttext .= ' '.
+ ' ';
+ }
+ $resulttext .= '';
+ my $position = $pos + 1;
+ $resulttext .= ''.&mt('Order: [_1]',$position).' ';
+ foreach my $key ('version','sigmethod','url','lifetime') {
+ if ($confhash{$provider}{$key} ne '') {
+ $resulttext .= ''.$lt{$key}.': '.$confhash{$provider}{$key}.' ';
+ }
+ }
+ if ($encconfhash{$provider}{'key'} ne '') {
+ $resulttext .= ''.$lt{'key'}.': '.$encconfhash{$provider}{'key'}.' ';
+ }
+ if ($encconfhash{$provider}{'secret'} ne '') {
+ $resulttext .= ''.$lt{'secret'}.': ';
+ my $num = length($encconfhash{$provider}{'secret'});
+ $resulttext .= ('*'x$num).' ';
+ }
+ my (@fields,$showroles);
+ if (ref($requserfields{$provider}) eq 'ARRAY') {
+ push(@fields,@{$requserfields{$provider}});
+ }
+ if (ref($confhash{$provider}{'fields'}) eq 'ARRAY') {
+ push(@fields,@{$confhash{$provider}{'fields'}});
+ } elsif (ref($confhash{$provider}{'fields'}) eq 'HASH') {
+ push(@fields,(keys(%{$confhash{$provider}{'fields'}})));
+ }
+ if (@fields) {
+ if (grep(/^roles$/,@fields)) {
+ $showroles = 1;
+ }
+ $resulttext .= ''.$lt{'udsl'}.': "'.
+ join('", "', map { $lt{$_}; } @fields).'" ';
+ }
+ if (ref($requserfields{$provider}) eq 'ARRAY') {
+ if (grep(/^user$/,@{$requserfields{$provider}})) {
+ if ($confhash{$provider}{'incdom'}) {
+ $resulttext .= ''.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'uname:dom'}).' ';
+ } else {
+ $resulttext .= ''.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'username'}).' ';
+ }
+ }
+ }
+ if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') {
+ if (@{$confhash{$provider}{'defaults'}} > 0) {
+ $resulttext .= ''.$lt{'defa'};
+ foreach my $field (@{$confhash{$provider}{'defaults'}}) {
+ $resulttext .= ' "'.$fieldtitles{$field}.'",';
+ }
+ $resulttext =~ s/,$//;
+ $resulttext .= ' ';
+ }
+ } elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') {
+ if (keys(%{$confhash{$provider}{'defaults'}})) {
+ $resulttext .= ''.$lt{'defa'}.': ';
+ foreach my $key (sort(keys(%{$confhash{$provider}{'defaults'}}))) {
+ if ($confhash{$provider}{'defaults'}{$key} ne '') {
+ $resulttext .= ''.$fieldtitles{$key}.' = '.$confhash{$provider}{'defaults'}{$key}.' ';
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ if (ref($crsconf{$provider}) eq 'ARRAY') {
+ if (@{$crsconf{$provider}} > 0) {
+ $resulttext .= ''.&mt('Configurable in course:');
+ my $numconfig = 0;
+ if (ref($confhash{$provider}{'crsconf'}) eq 'ARRAY') {
+ if (@{$confhash{$provider}{'crsconf'}} > 0) {
+ foreach my $field (@{$confhash{$provider}{'crsconf'}}) {
+ $numconfig ++;
+ if ($provider eq 'examity') {
+ $resulttext .= ' "'.$lt{'crs'.$field}.'",';
+ } else {
+ $resulttext .= ' "'.$fieldtitles{$field}.'",';
+ }
+ }
+ $resulttext =~ s/,$//;
+ }
+ }
+ if (!$numconfig) {
+ $resulttext .= ' '.&mt('None');
+ }
+ $resulttext .= ' ';
+ }
+ }
+ if ($showroles) {
+ if (ref($confhash{$provider}{'roles'}) eq 'HASH') {
+ my $rolemaps;
+ foreach my $role (@courseroles) {
+ if ($confhash{$provider}{'roles'}{$role}) {
+ $rolemaps .= (' 'x2).&Apache::lonnet::plaintext($role,'Course').'='.
+ $confhash{$provider}{'roles'}{$role}.',';
+ }
+ }
+ if ($rolemaps) {
+ $rolemaps =~ s/,$//;
+ $resulttext .= ''.&mt('Role mapping:').$rolemaps.' ';
+ }
+ }
+ }
+ if (ref($confhash{$provider}{'custom'}) eq 'HASH') {
+ my $customlist;
+ if (keys(%{$confhash{$provider}{'custom'}})) {
+ foreach my $key (sort(keys(%{$confhash{$provider}{'custom'}}))) {
+ $customlist .= $key.'='.$confhash{$provider}{'custom'}{$key}.', ';
+ }
+ $customlist =~ s/,$//;
+ }
+ if ($customlist) {
+ $resulttext .= ''.&mt('Custom items').': '.$customlist.' ';
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ $resulttext .= ' ';
+ } else {
+ $resulttext = &mt('No changes made.');
+ }
+ } else {
+ $errors .= ''.&mt('Failed to save changes').' ';
+ }
+ if ($errors) {
+ $resulttext .= &mt('The following errors occurred: ').'';
+ }
+ return $resulttext;
+}
+
+sub process_proctoring_image {
+ my ($r,$dom,$confname,$caller,$provider,$configuserok,$switchserver,$author_ok) = @_;
+ my $filename = $env{'form.'.$caller.'.filename'};
+ my ($error,$url);
+ my ($width,$height) = (21,21);
+ if ($configuserok eq 'ok') {
+ if ($switchserver) {
+ $error = &mt('Upload of Remote Proctoring Provider icon is not permitted to this server: [_1]',
+ $switchserver);
+ } elsif ($author_ok eq 'ok') {
+ my ($result,$imageurl,$madethumb) =
+ &publishlogo($r,'upload',$caller,$dom,$confname,
+ "proctoring/$provider/icon",$width,$height);
+ if ($result eq 'ok') {
+ if ($madethumb) {
+ my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
+ my $imagethumb = "$path/tn-".$imagefile;
+ $url = $imagethumb;
+ } else {
+ $url = $imageurl;
+ }
+ } else {
+ $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$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].",$filename,$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].",$filename,$confname,$dom,$configuserok);
+ }
+ return ($url,$error);
+}
+
sub modify_lti {
my ($r,$dom,$action,$lastactref,%domconfig) = @_;
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
@@ -11245,11 +14312,14 @@ sub modify_lti {
textbook => 'Textbook',
placement => 'Placement Test',
);
+ my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
my %lt = <i_names();
map { $posslti{$_} = 1; } @ltiroles;
map { $posslticrs{$_} = 1; } @lticourseroles;
map { $posscrstype{$_} = 1; } @coursetypes;
-
+
+ my %menutitles = <imenu_titles();
+
my (@items,%deletions,%itemids);
if ($env{'form.lti_add'}) {
my $consumer = $env{'form.lti_consumer_add'};
@@ -11291,7 +14361,7 @@ sub modify_lti {
if ($position ne '') {
$allpos[$position] = $itemid;
}
- foreach my $item ('consumer','key','secret','lifetime') {
+ foreach my $item ('consumer','key','secret','lifetime','requser') {
my $formitem = 'form.lti_'.$item.'_'.$idx;
$env{$formitem} =~ s/(`)/'/g;
if ($item eq 'lifetime') {
@@ -11313,127 +14383,186 @@ sub modify_lti {
if ($env{'form.lti_version_'.$idx} eq 'LTI-1p0') {
$confhash{$itemid}{'version'} = $env{'form.lti_version_'.$idx};
}
- if ($env{'form.lti_mapuser_'.$idx} eq 'sourcedid') {
- $confhash{$itemid}{'mapuser'} = 'lis_person_sourcedid';
- } elsif ($env{'form.lti_mapuser_'.$idx} eq 'email') {
- $confhash{$itemid}{'mapuser'} = 'lis_person_contact_email_primary';
- } elsif ($env{'form.lti_mapuser_'.$idx} eq 'other') {
- my $mapuser = $env{'form.lti_customuser_'.$idx};
- $mapuser =~ s/(`)/'/g;
- $mapuser =~ s/^\s+|\s+$//g;
- $confhash{$itemid}{'mapuser'} = $mapuser;
- }
- foreach my $ltirole (@lticourseroles) {
- my $possrole = $env{'form.lti_maprole_'.$ltirole.'_'.$idx};
- if (grep(/^\Q$possrole\E$/,@courseroles)) {
- $confhash{$itemid}{'maproles'}{$ltirole} = $possrole;
- }
- }
- my @possmakeuser = &Apache::loncommon::get_env_multiple('form.lti_makeuser_'.$idx);
- my @makeuser;
- foreach my $ltirole (sort(@possmakeuser)) {
- if ($posslti{$ltirole}) {
- push(@makeuser,$ltirole);
- }
- }
- $confhash{$itemid}{'makeuser'} = \@makeuser;
- if (($env{'form.lti_mapcrs_'.$idx} eq 'course_offering_sourcedid') ||
- ($env{'form.lti_mapcrs_'.$idx} eq 'context_id')) {
- $confhash{$itemid}{'mapcrs'} = $env{'form.lti_mapcrs_'.$idx};
- } elsif ($env{'form.lti_mapcrs_'.$idx} eq 'other') {
- my $mapcrs = $env{'form.lti_mapcrsfield_'.$idx};
- $mapcrs =~ s/(`)/'/g;
- $mapcrs =~ s/^\s+|\s+$//g;
- $confhash{$itemid}{'mapcrs'} = $mapcrs;
- }
- my @posstypes = &Apache::loncommon::get_env_multiple('form.lti_mapcrstype_'.$idx);
- my @crstypes;
- foreach my $type (sort(@posstypes)) {
- if ($posscrstype{$type}) {
- push(@crstypes,$type);
+ if ($confhash{$itemid}{'requser'}) {
+ if ($env{'form.lti_mapuser_'.$idx} eq 'sourcedid') {
+ $confhash{$itemid}{'mapuser'} = 'lis_person_sourcedid';
+ } elsif ($env{'form.lti_mapuser_'.$idx} eq 'email') {
+ $confhash{$itemid}{'mapuser'} = 'lis_person_contact_email_primary';
+ } elsif ($env{'form.lti_mapuser_'.$idx} eq 'other') {
+ my $mapuser = $env{'form.lti_customuser_'.$idx};
+ $mapuser =~ s/(`)/'/g;
+ $mapuser =~ s/^\s+|\s+$//g;
+ $confhash{$itemid}{'mapuser'} = $mapuser;
+ }
+ foreach my $ltirole (@lticourseroles) {
+ my $possrole = $env{'form.lti_maprole_'.$ltirole.'_'.$idx};
+ if (grep(/^\Q$possrole\E$/,@courseroles)) {
+ $confhash{$itemid}{'maproles'}{$ltirole} = $possrole;
+ }
+ }
+ my @possmakeuser = &Apache::loncommon::get_env_multiple('form.lti_makeuser_'.$idx);
+ my @makeuser;
+ foreach my $ltirole (sort(@possmakeuser)) {
+ if ($posslti{$ltirole}) {
+ push(@makeuser,$ltirole);
+ }
+ }
+ $confhash{$itemid}{'makeuser'} = \@makeuser;
+ if (@makeuser) {
+ my $lcauth = $env{'form.lti_lcauth_'.$idx};
+ if ($lcauth =~ /^(internal|krb4|krb5|localauth)$/) {
+ $confhash{$itemid}{'lcauth'} = $lcauth;
+ if ($lcauth ne 'internal') {
+ my $lcauthparm = $env{'form.lti_lcauthparm_'.$idx};
+ $lcauthparm =~ s/^(\s+|\s+)$//g;
+ $lcauthparm =~ s/`//g;
+ if ($lcauthparm ne '') {
+ $confhash{$itemid}{'lcauthparm'} = $lcauthparm;
+ }
+ }
+ } else {
+ $confhash{$itemid}{'lcauth'} = 'lti';
+ }
}
- }
- $confhash{$itemid}{'mapcrstype'} = \@crstypes;
- if ($env{'form.lti_makecrs_'.$idx}) {
- $confhash{$itemid}{'makecrs'} = 1;
- }
- my @possenroll = &Apache::loncommon::get_env_multiple('form.lti_selfenroll_'.$idx);
- my @selfenroll;
- foreach my $type (sort(@possenroll)) {
- if ($posslticrs{$type}) {
- push(@selfenroll,$type);
+ my @possinstdata = &Apache::loncommon::get_env_multiple('form.lti_instdata_'.$idx);
+ if (@possinstdata) {
+ foreach my $field (@possinstdata) {
+ if (exists($fieldtitles{$field})) {
+ push(@{$confhash{$itemid}{'instdata'}});
+ }
+ }
}
- }
- $confhash{$itemid}{'selfenroll'} = \@selfenroll;
- if ($env{'form.lti_crssec_'.$idx}) {
- if ($env{'form.lti_crssecsrc_'.$idx} eq 'course_section_sourcedid') {
- $confhash{$itemid}{'section'} = $env{'form.lti_crssecsrc_'.$idx};
- } elsif ($env{'form.lti_crssecsrc_'.$idx} eq 'other') {
- my $section = $env{'form.lti_customsection_'.$idx};
- $section =~ s/(`)/'/g;
- $section =~ s/^\s+|\s+$//g;
- if ($section ne '') {
- $confhash{$itemid}{'section'} = $section;
+ if (($env{'form.lti_mapcrs_'.$idx} eq 'course_offering_sourcedid') ||
+ ($env{'form.lti_mapcrs_'.$idx} eq 'context_id')) {
+ $confhash{$itemid}{'mapcrs'} = $env{'form.lti_mapcrs_'.$idx};
+ } elsif ($env{'form.lti_mapcrs_'.$idx} eq 'other') {
+ my $mapcrs = $env{'form.lti_mapcrsfield_'.$idx};
+ $mapcrs =~ s/(`)/'/g;
+ $mapcrs =~ s/^\s+|\s+$//g;
+ $confhash{$itemid}{'mapcrs'} = $mapcrs;
+ }
+ my @posstypes = &Apache::loncommon::get_env_multiple('form.lti_mapcrstype_'.$idx);
+ my @crstypes;
+ foreach my $type (sort(@posstypes)) {
+ if ($posscrstype{$type}) {
+ push(@crstypes,$type);
}
}
- }
- foreach my $field ('passback','roster') {
- if ($env{'form.lti_'.$field.'_'.$idx}) {
- $confhash{$itemid}{$field} = 1;
+ $confhash{$itemid}{'mapcrstype'} = \@crstypes;
+ if ($env{'form.lti_makecrs_'.$idx}) {
+ $confhash{$itemid}{'makecrs'} = 1;
}
- }
- unless (($idx eq 'add') || ($changes{$itemid})) {
- foreach my $field ('mapuser','mapcrs','section','passback','roster') {
- if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
- $changes{$itemid} = 1;
+ my @possenroll = &Apache::loncommon::get_env_multiple('form.lti_selfenroll_'.$idx);
+ my @selfenroll;
+ foreach my $type (sort(@possenroll)) {
+ if ($posslticrs{$type}) {
+ push(@selfenroll,$type);
}
}
- foreach my $field ('makeuser','mapcrstype','selfenroll') {
- unless ($changes{$itemid}) {
- if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
- if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
- my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
- $confhash{$itemid}{$field});
- if (@diffs) {
- $changes{$itemid} = 1;
- }
- } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
- $changes{$itemid} = 1;
+ $confhash{$itemid}{'selfenroll'} = \@selfenroll;
+ if ($env{'form.lti_crssec_'.$idx}) {
+ if ($env{'form.lti_crssecsrc_'.$idx} eq 'course_section_sourcedid') {
+ $confhash{$itemid}{'section'} = $env{'form.lti_crssecsrc_'.$idx};
+ } elsif ($env{'form.lti_crssecsrc_'.$idx} eq 'other') {
+ my $section = $env{'form.lti_customsection_'.$idx};
+ $section =~ s/(`)/'/g;
+ $section =~ s/^\s+|\s+$//g;
+ if ($section ne '') {
+ $confhash{$itemid}{'section'} = $section;
+ }
+ }
+ }
+ if ($env{'form.lti_callback_'.$idx}) {
+ if ($env{'form.lti_callbackparam_'.$idx}) {
+ my $callback = $env{'form.lti_callbackparam_'.$idx};
+ $callback =~ s/^\s+|\s+$//g;
+ $confhash{$itemid}{'callback'} = $callback;
+ }
+ }
+ foreach my $field ('passback','roster','topmenu','inlinemenu') {
+ if ($env{'form.lti_'.$field.'_'.$idx}) {
+ $confhash{$itemid}{$field} = 1;
+ }
+ }
+ if ($env{'form.lti_passback_'.$idx}) {
+ if ($env{'form.lti_passbackformat_'.$idx} eq '1.0') {
+ $confhash{$itemid}{'passbackformat'} = '1.0';
+ } else {
+ $confhash{$itemid}{'passbackformat'} = '1.1';
+ }
+ }
+ if ($env{'form.lti_topmenu_'.$idx} || $env{'form.lti_inlinemenu_'.$idx}) {
+ $confhash{$itemid}{lcmenu} = [];
+ my @possmenu = &Apache::loncommon::get_env_multiple('form.lti_menuitem_'.$idx);
+ foreach my $field (@possmenu) {
+ if (exists($menutitles{$field})) {
+ if ($field eq 'grades') {
+ next unless ($env{'form.lti_inlinemenu_'.$idx});
}
- } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{$field}} > 0) {
+ push(@{$confhash{$itemid}{lcmenu}},$field);
+ }
+ }
+ }
+ unless (($idx eq 'add') || ($changes{$itemid})) {
+ foreach my $field ('mapuser','mapcrs','makecrs','section','passback','roster','lcauth','lcauthparm','topmenu','inlinemenu','callback') {
+ if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
+ $changes{$itemid} = 1;
+ }
+ }
+ unless ($changes{$itemid}) {
+ if ($domconfig{$action}{$itemid}{'passback'} eq $confhash{$itemid}{'passback'}) {
+ if ($domconfig{$action}{$itemid}{'passbackformat'} ne $confhash{$itemid}{'passbackformat'}) {
$changes{$itemid} = 1;
}
- }
+ }
}
- }
- unless ($changes{$itemid}) {
- if (ref($domconfig{$action}{$itemid}{'maproles'}) eq 'HASH') {
- if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
- foreach my $ltirole (keys(%{$domconfig{$action}{$itemid}{'maproles'}})) {
- if ($domconfig{$action}{$itemid}{'maproles'}{$ltirole} ne
- $confhash{$itemid}{'maproles'}{$ltirole}) {
+ foreach my $field ('makeuser','mapcrstype','selfenroll','instdata','lcmenu') {
+ unless ($changes{$itemid}) {
+ if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
+ if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
+ $confhash{$itemid}{$field});
+ if (@diffs) {
+ $changes{$itemid} = 1;
+ }
+ } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
+ $changes{$itemid} = 1;
+ }
+ } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{$field}} > 0) {
$changes{$itemid} = 1;
- last;
}
}
- unless ($changes{$itemid}) {
- foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
- if ($confhash{$itemid}{'maproles'}{$ltirole} ne
- $domconfig{$action}{$itemid}{'maproles'}{$ltirole}) {
+ }
+ }
+ unless ($changes{$itemid}) {
+ if (ref($domconfig{$action}{$itemid}{'maproles'}) eq 'HASH') {
+ if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ foreach my $ltirole (keys(%{$domconfig{$action}{$itemid}{'maproles'}})) {
+ if ($domconfig{$action}{$itemid}{'maproles'}{$ltirole} ne
+ $confhash{$itemid}{'maproles'}{$ltirole}) {
$changes{$itemid} = 1;
last;
}
}
- }
- } elsif (keys(%{$domconfig{$action}{$itemid}{'maproles'}}) > 0) {
- $changes{$itemid} = 1;
- }
- } elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
- unless ($changes{$itemid}) {
- if (keys(%{$confhash{$itemid}{'maproles'}}) > 0) {
+ unless ($changes{$itemid}) {
+ foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
+ if ($confhash{$itemid}{'maproles'}{$ltirole} ne
+ $domconfig{$action}{$itemid}{'maproles'}{$ltirole}) {
+ $changes{$itemid} = 1;
+ last;
+ }
+ }
+ }
+ } elsif (keys(%{$domconfig{$action}{$itemid}{'maproles'}}) > 0) {
$changes{$itemid} = 1;
}
+ } elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ unless ($changes{$itemid}) {
+ if (keys(%{$confhash{$itemid}{'maproles'}}) > 0) {
+ $changes{$itemid} = 1;
+ }
+ }
}
}
}
@@ -11506,84 +14635,130 @@ sub modify_lti {
my $num = length($encconfig{$itemid}{'secret'});
$resulttext .= ('*'x$num).'';
}
- if ($confhash{$itemid}{'mapuser'}) {
- my $shownmapuser;
- if ($confhash{$itemid}{'mapuser'} eq 'lis_person_sourcedid') {
- $shownmapuser = $lt{'sourcedid'}.' (lis_person_sourcedid)';
- } elsif ($confhash{$itemid}{'mapuser'} eq 'lis_person_contact_email_primary') {
- $shownmapuser = $lt{'email'}.' (lis_person_contact_email_primary)';
- } else {
- $shownmapuser = &mt('Other').' ('.$confhash{$itemid}{'mapuser'}.')';
- }
- $resulttext .= ''.&mt('LON-CAPA username').': '.$shownmapuser.' ';
- }
- if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
- my $rolemaps;
- foreach my $role (@ltiroles) {
- if ($confhash{$itemid}{'maproles'}{$role}) {
- $rolemaps .= (' 'x2).$role.'='.
- &Apache::lonnet::plaintext($confhash{$itemid}{'maproles'}{$role},
- 'Course').',';
+ if ($confhash{$itemid}{'requser'}) {
+ if ($confhash{$itemid}{'mapuser'}) {
+ my $shownmapuser;
+ if ($confhash{$itemid}{'mapuser'} eq 'lis_person_sourcedid') {
+ $shownmapuser = $lt{'sourcedid'}.' (lis_person_sourcedid)';
+ } elsif ($confhash{$itemid}{'mapuser'} eq 'lis_person_contact_email_primary') {
+ $shownmapuser = $lt{'email'}.' (lis_person_contact_email_primary)';
+ } else {
+ $shownmapuser = &mt('Other').' ('.$confhash{$itemid}{'mapuser'}.')';
}
+ $resulttext .= ''.&mt('LON-CAPA username').': '.$shownmapuser.' ';
}
- if ($rolemaps) {
- $rolemaps =~ s/,$//;
- $resulttext .= ''.&mt('Role mapping:').$rolemaps.' ';
+ if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ my $rolemaps;
+ foreach my $role (@ltiroles) {
+ if ($confhash{$itemid}{'maproles'}{$role}) {
+ $rolemaps .= (' 'x2).$role.'='.
+ &Apache::lonnet::plaintext($confhash{$itemid}{'maproles'}{$role},
+ 'Course').',';
+ }
+ }
+ if ($rolemaps) {
+ $rolemaps =~ s/,$//;
+ $resulttext .= ''.&mt('Role mapping:').$rolemaps.' ';
+ }
+ }
+ if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'makeuser'}} > 0) {
+ $resulttext .= ''.&mt('Following roles may create user accounts: [_1]',
+ join(', ',@{$confhash{$itemid}{'makeuser'}})).' ';
+ if ($confhash{$itemid}{'lcauth'} eq 'lti') {
+ $resulttext .= &mt('New users will only be able to authenticate via LTI').' ';
+ } else {
+ $resulttext .= &mt('New users will be assigned LON-CAPA authentication: [_1]',
+ $confhash{$itemid}{'lcauth'});
+ if ($confhash{$itemid}{'lcauth'} eq 'internal') {
+ $resulttext .= '; '.&mt('a randomly generated password will be created');
+ } elsif ($confhash{$itemid}{'lcauth'} eq 'localauth') {
+ if ($confhash{$itemid}{'lcauthparm'} ne '') {
+ $resulttext .= ' '.&mt('with argument: [_1]',$confhash{$itemid}{'lcauthparm'});
+ }
+ } else {
+ $resulttext .= '; '.&mt('Kerberos domain: [_1]',$confhash{$itemid}{'lcauthparm'});
+ }
+ }
+ $resulttext .= '';
+ } else {
+ $resulttext .= ''.&mt('User account creation not permitted.').' ';
+ }
}
- }
- if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'makeuser'}} > 0) {
- $resulttext .= ''.&mt('Following roles may create user accounts: [_1]',
- join(', ',@{$confhash{$itemid}{'makeuser'}})).' ';
- } else {
- $resulttext .= ''.&mt('User account creation not permitted.').' ';
+ if (ref($confhash{$itemid}{'instdata'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'instdata'}} > 0) {
+ $resulttext .= ''.&mt('Institutional data will be used when creating a new user for: [_1]',
+ join(', ',map { $fieldtitles{$_}; } @{$confhash{$itemid}{'instdata'}})).' ';
+ } else {
+ $resulttext .= ''.&mt('No institutional data used when creating a new user.').' ';
+ }
}
- }
- if ($confhash{$itemid}{'mapcrs'}) {
- $resulttext .= ''.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.' ';
- }
- if (ref($confhash{$itemid}{'mapcrstype'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'mapcrstype'}} > 0) {
- $resulttext .= ''.&mt('Mapping for the following LON-CAPA course types: [_1]',
- join(', ',map { $coursetypetitles{$_}; } @coursetypes)).
- ' ';
- } else {
- $resulttext .= ''.&mt('No mapping to LON-CAPA courses').' ';
+ if ($confhash{$itemid}{'mapcrs'}) {
+ $resulttext .= ''.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.' ';
}
- }
- if ($confhash{$itemid}{'makecrs'}) {
- $resulttext .= ''.&mt('Instructor may create course (if absent).').' ';
- } else {
- $resulttext .= ''.&mt('Instructor may not create course (if absent).').' ';
- }
- if (ref($confhash{$itemid}{'selfenroll'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'selfenroll'}} > 0) {
- $resulttext .= ''.&mt('Self-enrollment for following roles: [_1]',
- join(', ',@{$confhash{$itemid}{'selfenroll'}})).
- ' ';
+ if (ref($confhash{$itemid}{'mapcrstype'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'mapcrstype'}} > 0) {
+ $resulttext .= ''.&mt('Mapping for the following LON-CAPA course types: [_1]',
+ join(', ',map { $coursetypetitles{$_}; } @coursetypes)).
+ ' ';
+ } else {
+ $resulttext .= ''.&mt('No mapping to LON-CAPA courses').' ';
+ }
+ }
+ if ($confhash{$itemid}{'makecrs'}) {
+ $resulttext .= ''.&mt('Instructor may create course (if absent).').' ';
} else {
- $resulttext .= ''.&mt('Self-enrollment not permitted').' ';
+ $resulttext .= ''.&mt('Instructor may not create course (if absent).').' ';
}
- }
- if ($confhash{$itemid}{'section'}) {
- if ($confhash{$itemid}{'section'} eq 'course_section_sourcedid') {
- $resulttext .= ''.&mt('User section from standard field:').
- ' (course_section_sourcedid)'.' ';
+ if (ref($confhash{$itemid}{'selfenroll'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'selfenroll'}} > 0) {
+ $resulttext .= ''.&mt('Self-enrollment for following roles: [_1]',
+ join(', ',@{$confhash{$itemid}{'selfenroll'}})).
+ ' ';
+ } else {
+ $resulttext .= ''.&mt('Self-enrollment not permitted').' ';
+ }
+ }
+ if ($confhash{$itemid}{'section'}) {
+ if ($confhash{$itemid}{'section'} eq 'course_section_sourcedid') {
+ $resulttext .= ''.&mt('User section from standard field:').
+ ' (course_section_sourcedid)'.' ';
+ } else {
+ $resulttext .= ''.&mt('User section from:').' '.
+ $confhash{$itemid}{'section'}.' ';
+ }
} else {
- $resulttext .= ''.&mt('User section from:').' '.
- $confhash{$itemid}{'section'}.' ';
+ $resulttext .= ''.&mt('No section assignment').' ';
}
- } else {
- $resulttext .= ''.&mt('No section assignment').' ';
- }
- foreach my $item ('passback','roster') {
- $resulttext .= ''.$lt{$item}.' ';
- if ($confhash{$itemid}{$item}) {
- $resulttext .= &mt('Yes');
+ if ($confhash{$itemid}{'callback'}) {
+ $resulttext .= ' '.&mt('Callback setting').': '.$confhash{$itemid}{'callback'}.' ';
} else {
- $resulttext .= &mt('No');
+ $resulttext .= ''.&mt('No callback to logout LON-CAPA session when user logs out of Comsumer');
+ }
+ foreach my $item ('passback','roster','topmenu','inlinemenu') {
+ $resulttext .= ' '.$lt{$item}.': ';
+ if ($confhash{$itemid}{$item}) {
+ $resulttext .= &mt('Yes');
+ if ($item eq 'passback') {
+ if ($confhash{$itemid}{'passbackformat'} eq '1.0') {
+ $resulttext .= ' ('.&mt('Outcomes Extension (1.0)').')';
+ } elsif ($confhash{$itemid}{'passbackformat'} eq '1.1') {
+ $resulttext .= ' ('.&mt('Outcomes Service (1.1)').')';
+ }
+ }
+ } else {
+ $resulttext .= &mt('No');
+ }
+ $resulttext .= ' ';
+ }
+ if (ref($confhash{$itemid}{'lcmenu'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'lcmenu'}} > 0) {
+ $resulttext .= ''.&mt('Menu items:').' '.
+ join(', ', map { $menutitles{$_}; } (@{$confhash{$itemid}{'lcmenu'}})).' ';
+ } else {
+ $resulttext .= ''.&mt('No menu items displayed in header or online menu').' ';
+ }
}
- $resulttext .= '';
}
$resulttext .= ' ';
}
@@ -12230,8 +15405,9 @@ sub modify_contacts {
my (%others,%to,%bcc,%includestr,%includeloc);
my @contacts = ('supportemail','adminemail');
my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',
- 'lonstatusmail','requestsmail','updatesmail','idconflictsmail');
- my @toggles = ('reporterrors','reportupdates');
+ 'lonstatusmail','requestsmail','updatesmail','idconflictsmail','hostipmail');
+ my @toggles = ('reporterrors','reportupdates','reportstatus');
+ my @lonstatus = ('threshold','sysmail','weights','excluded');
my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
foreach my $type (@mailings) {
@{$newsetting{$type}} =
@@ -12264,6 +15440,41 @@ sub modify_contacts {
$contacts_hash{'contacts'}{$item} = $env{'form.'.$item};
}
}
+ my ($lonstatus_defs,$lonstatus_names) = &Apache::loncommon::lon_status_items();
+ foreach my $item (@lonstatus) {
+ if ($item eq 'excluded') {
+ my (%serverhomes,@excluded);
+ map { $serverhomes{$_} = 1; } values(%Apache::lonnet::serverhomeIDs);
+ my @possexcluded = &Apache::loncommon::get_env_multiple('form.errorexcluded');
+ if (@possexcluded) {
+ foreach my $id (sort(@possexcluded)) {
+ if ($serverhomes{$id}) {
+ push(@excluded,$id);
+ }
+ }
+ }
+ if (@excluded) {
+ $contacts_hash{'contacts'}{'lonstatus'}{$item} = \@excluded;
+ }
+ } elsif ($item eq 'weights') {
+ foreach my $type ('E','W','N','U') {
+ $env{'form.error'.$item.'_'.$type} =~ s/^\s+|\s+$//g;
+ if ($env{'form.error'.$item.'_'.$type} =~ /^\d+$/) {
+ unless ($env{'form.error'.$item.'_'.$type} == $lonstatus_defs->{$type}) {
+ $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type} =
+ $env{'form.error'.$item.'_'.$type};
+ }
+ }
+ }
+ } elsif (($item eq 'threshold') || ($item eq 'sysmail')) {
+ $env{'form.error'.$item} =~ s/^\s+|\s+$//g;
+ if ($env{'form.error'.$item} =~ /^\d+$/) {
+ unless ($env{'form.error'.$item} == $lonstatus_defs->{$item}) {
+ $contacts_hash{'contacts'}{'lonstatus'}{$item} = $env{'form.error'.$item};
+ }
+ }
+ }
+ }
if ((ref($fields) eq 'ARRAY') && (ref($possoptions) eq 'HASH')) {
foreach my $field (@{$fields}) {
if (ref($possoptions->{$field}) eq 'ARRAY') {
@@ -12402,6 +15613,76 @@ sub modify_contacts {
}
}
}
+ if (ref($currsetting{'lonstatus'}) eq 'HASH') {
+ foreach my $key ('excluded','weights','threshold','sysmail') {
+ if ($key eq 'excluded') {
+ if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&
+ (ref($contacts_hash{contacts}{lonstatus}{excluded}) eq 'ARRAY')) {
+ if ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&
+ (@{$currsetting{'lonstatus'}{$key}})) {
+ my @diffs =
+ &Apache::loncommon::compare_arrays($contacts_hash{contacts}{lonstatus}{excluded},
+ $currsetting{'lonstatus'}{$key});
+ if (@diffs) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ } elsif (@{$contacts_hash{contacts}{lonstatus}{excluded}}) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ } elsif ((ref($currsetting{'lonstatus'}{$key}) eq 'ARRAY') &&
+ (@{$currsetting{'lonstatus'}{$key}})) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ } elsif ($key eq 'weights') {
+ if ((ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') &&
+ (ref($contacts_hash{contacts}{lonstatus}{$key}) eq 'HASH')) {
+ if (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {
+ foreach my $type ('E','W','N','U') {
+ unless ($contacts_hash{contacts}{lonstatus}{$key}{$type} eq
+ $currsetting{'lonstatus'}{$key}{$type}) {
+ push(@{$changes{'lonstatus'}},$key);
+ last;
+ }
+ }
+ } else {
+ foreach my $type ('E','W','N','U') {
+ if ($contacts_hash{contacts}{lonstatus}{$key}{$type} ne '') {
+ push(@{$changes{'lonstatus'}},$key);
+ last;
+ }
+ }
+ }
+ } elsif (ref($currsetting{'lonstatus'}{$key}) eq 'HASH') {
+ foreach my $type ('E','W','N','U') {
+ if ($currsetting{'lonstatus'}{$key}{$type} ne '') {
+ push(@{$changes{'lonstatus'}},$key);
+ last;
+ }
+ }
+ }
+ } elsif (($key eq 'threshold') || ($key eq 'sysmail')) {
+ if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
+ if ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {
+ if ($currsetting{'lonstatus'}{$key} != $contacts_hash{contacts}{lonstatus}{$key}) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ } elsif ($contacts_hash{contacts}{lonstatus}{$key} =~ /^\d+$/) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ } elsif ($currsetting{'lonstatus'}{$key} =~ /^\d+$/) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ }
+ }
+ } else {
+ if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
+ foreach my $key ('excluded','weights','threshold','sysmail') {
+ if (exists($contacts_hash{contacts}{lonstatus}{$key})) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ }
+ }
+ }
} else {
my %default;
$default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
@@ -12413,6 +15694,7 @@ sub modify_contacts {
$default{'lonstatusmail'} = 'adminemail';
$default{'requestsmail'} = 'adminemail';
$default{'updatesmail'} = 'adminemail';
+ $default{'hostipmail'} = 'adminemail';
foreach my $item (@contacts) {
if ($to{$item} ne $default{$item}) {
$changes{$item} = 1;
@@ -12446,6 +15728,13 @@ sub modify_contacts {
}
}
}
+ if (ref($contacts_hash{contacts}{lonstatus}) eq 'HASH') {
+ foreach my $key ('excluded','weights','threshold','sysmail') {
+ if (exists($contacts_hash{contacts}{lonstatus}{$key})) {
+ push(@{$changes{'lonstatus'}},$key);
+ }
+ }
+ }
}
foreach my $item (@toggles) {
if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) {
@@ -12571,22 +15860,79 @@ sub modify_contacts {
}
}
my @offon = ('off','on');
+ my $corelink = &core_link_msu();
if ($changes{'reporterrors'}) {
$resulttext .= ''.
&mt('E-mail error reports to [_1] set to "'.
$offon[$env{'form.reporterrors'}].'".',
- &Apache::loncommon::modal_link('http://loncapa.org/core.html',
- &mt('LON-CAPA core group - MSU'),600,500)).
+ $corelink).
' ';
}
if ($changes{'reportupdates'}) {
$resulttext .= ''.
&mt('E-mail record of completed LON-CAPA updates to [_1] set to "'.
$offon[$env{'form.reportupdates'}].'".',
- &Apache::loncommon::modal_link('http://loncapa.org/core.html',
- &mt('LON-CAPA core group - MSU'),600,500)).
+ $corelink).
+ ' ';
+ }
+ if ($changes{'reportstatus'}) {
+ $resulttext .= ''.
+ &mt('E-mail status if errors above threshold to [_1] set to "'.
+ $offon[$env{'form.reportstatus'}].'".',
+ $corelink).
' ';
}
+ if (ref($changes{'lonstatus'}) eq 'ARRAY') {
+ $resulttext .= ''.
+ &mt('Nightly status check e-mail settings').':';
+ my (%defval,%use_def,%shown);
+ $defval{'threshold'} = $lonstatus_defs->{'threshold'};
+ $defval{'sysmail'} = $lonstatus_defs->{'sysmail'};
+ $defval{'weights'} =
+ join(', ',map { $lonstatus_names->{$_}.'='.$lonstatus_defs->{$_}; } ('E','W','N','U'));
+ $defval{'excluded'} = &mt('None');
+ if (ref($contacts_hash{'contacts'}{'lonstatus'}) eq 'HASH') {
+ foreach my $item ('threshold','sysmail','weights','excluded') {
+ if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item})) {
+ if (($item eq 'threshold') || ($item eq 'sysmail')) {
+ $shown{$item} = $contacts_hash{'contacts'}{'lonstatus'}{$item};
+ } elsif ($item eq 'weights') {
+ if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'HASH') {
+ foreach my $type ('E','W','N','U') {
+ $shown{$item} .= $lonstatus_names->{$type}.'=';
+ if (exists($contacts_hash{'contacts'}{'lonstatus'}{$item}{$type})) {
+ $shown{$item} .= $contacts_hash{'contacts'}{'lonstatus'}{$item}{$type};
+ } else {
+ $shown{$item} .= $lonstatus_defs->{$type};
+ }
+ $shown{$item} .= ', ';
+ }
+ $shown{$item} =~ s/, $//;
+ } else {
+ $shown{$item} = $defval{$item};
+ }
+ } elsif ($item eq 'excluded') {
+ if (ref($contacts_hash{'contacts'}{'lonstatus'}{$item}) eq 'ARRAY') {
+ $shown{$item} = join(', ',@{$contacts_hash{'contacts'}{'lonstatus'}{$item}});
+ } else {
+ $shown{$item} = $defval{$item};
+ }
+ }
+ } else {
+ $shown{$item} = $defval{$item};
+ }
+ }
+ } else {
+ foreach my $item ('threshold','weights','excluded','sysmail') {
+ $shown{$item} = $defval{$item};
+ }
+ }
+ foreach my $item ('threshold','weights','excluded','sysmail') {
+ $resulttext .= ''.&mt($titles->{'error'.$item}.' -- [_1]',
+ $shown{$item}).' ';
+ }
+ $resulttext .= ' ';
+ }
if ((ref($changes{'helpform'}) eq 'ARRAY') && (ref($fields) eq 'ARRAY')) {
my (@optional,@required,@unused,$maxsizechg);
foreach my $field (@{$changes{'helpform'}}) {
@@ -12638,6 +15984,778 @@ sub modify_contacts {
return $resulttext;
}
+sub modify_privacy {
+ my ($dom,%domconfig) = @_;
+ my ($resulttext,%current,%changes);
+ if (ref($domconfig{'privacy'}) eq 'HASH') {
+ %current = %{$domconfig{'privacy'}};
+ }
+ my @fields = ('lastname','firstname','middlename','generation','permanentemail','id');
+ my @items = ('domain','author','course','community');
+ my %names = &Apache::lonlocal::texthash (
+ domain => 'Assigned domain role(s)',
+ author => 'Assigned co-author role(s)',
+ course => 'Assigned course role(s)',
+ community => 'Assigned community role',
+ );
+ my %roles = &Apache::lonlocal::texthash (
+ domain => 'Domain role',
+ author => 'Co-author role',
+ course => 'Course role',
+ community => 'Community role',
+ );
+ my %titles = &Apache::lonlocal::texthash (
+ approval => 'Approval for role in different domain',
+ othdom => 'User information available in other domain',
+ priv => 'Information viewable by privileged user in same domain',
+ unpriv => 'Information viewable by unprivileged user in same domain',
+ instdom => 'Other domain shares institution/provider',
+ extdom => 'Other domain has different institution/provider',
+ none => 'Not allowed',
+ user => 'User authorizes',
+ domain => 'Domain Coordinator authorizes',
+ auto => 'Unrestricted',
+ );
+ my %fieldnames = &Apache::lonlocal::texthash (
+ id => 'Student/Employee ID',
+ permanentemail => 'E-mail address',
+ lastname => 'Last Name',
+ firstname => 'First Name',
+ middlename => 'Middle Name',
+ generation => 'Generation',
+ );
+ my ($othertitle,$usertypes,$types) =
+ &Apache::loncommon::sorted_inst_types($dom);
+ my (%by_ip,%by_location,@intdoms,@instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+
+ my %privacyhash = (
+ 'approval' => {
+ instdom => {},
+ extdom => {},
+ },
+ 'othdom' => {},
+ 'priv' => {},
+ 'unpriv' => {},
+ );
+ foreach my $item (@items) {
+ if (@instdoms > 1) {
+ if ($env{'form.privacy_approval_instdom'.$item} =~ /^(none|user|domain|auto)$/) {
+ $privacyhash{'approval'}{'instdom'}{$item} = $env{'form.privacy_approval_instdom_'.$item};
+ }
+ if (ref($current{'approval'}) eq 'HASH') {
+ if (ref($current{'approval'}{'instdom'}) eq 'HASH') {
+ unless ($privacyhash{'approval'}{'instdom'}{$item} eq $current{'approval'}{'instdom'}{$item}) {
+ $changes{'approval'} = 1;
+ }
+ }
+ } elsif ($privacyhash{'approval'}{'instdom'}{$item} ne 'auto') {
+ $changes{'approval'} = 1;
+ }
+ }
+ if (keys(%by_location) > 0) {
+ if ($env{'form.privacy_approval_extdom_'.$item} =~ /^(none|user|domain|auto)$/) {
+ $privacyhash{'approval'}{'extdom'}{$item} = $env{'form.privacy_approval_extdom_'.$item};
+ }
+ if (ref($current{'approval'}) eq 'HASH') {
+ if (ref($current{'approval'}{'extdom'}) eq 'HASH') {
+ unless ($privacyhash{'approval'}{'extdom'}{$item} eq $current{'approval'}{'extdom'}{$item}) {
+ $changes{'approval'} = 1;
+ }
+ }
+ } elsif ($privacyhash{'approval'}{'extdom'}{$item} ne 'auto') {
+ $changes{'approval'} = 1;
+ }
+ }
+ foreach my $status ('priv','unpriv') {
+ my @possibles = sort(&Apache::loncommon::get_env_multiple('form.privacy_'.$status.'_'.$item));
+ my @newvalues;
+ foreach my $field (@possibles) {
+ if (grep(/^\Q$field\E$/,@fields)) {
+ $privacyhash{$status}{$item}{$field} = 1;
+ push(@newvalues,$field);
+ }
+ }
+ @newvalues = sort(@newvalues);
+ if (ref($current{$status}) eq 'HASH') {
+ if (ref($current{$status}{$item}) eq 'HASH') {
+ my @currvalues = sort(keys(%{$current{$status}{$item}}));
+ my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
+ if (@diffs > 0) {
+ $changes{$status} = 1;
+ }
+ }
+ } else {
+ my @stdfields;
+ foreach my $field (@fields) {
+ if ($field eq 'id') {
+ next if ($status eq 'unpriv');
+ next if (($status eq 'priv') && ($item eq 'community'));
+ }
+ push(@stdfields,$field);
+ }
+ my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
+ if (@diffs > 0) {
+ $changes{$status} = 1;
+ }
+ }
+ }
+ }
+ if ((@instdoms > 1) || (keys(%by_location) > 0)) {
+ my @statuses;
+ if (ref($types) eq 'ARRAY') {
+ @statuses = @{$types};
+ }
+ foreach my $type (@statuses,'default') {
+ my @possfields = &Apache::loncommon::get_env_multiple('form.privacy_othdom_'.$type);
+ my @newvalues;
+ foreach my $field (sort(@possfields)) {
+ if (grep(/^\Q$field\E$/,@fields)) {
+ $privacyhash{'othdom'}{$type}{$field} = 1;
+ push(@newvalues,$field);
+ }
+ }
+ @newvalues = sort(@newvalues);
+ if (ref($current{'othdom'}) eq 'HASH') {
+ if (ref($current{'othdom'}{$type}) eq 'HASH') {
+ my @currvalues = sort(keys(%{$current{'othdom'}{$type}}));
+ my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
+ if (@diffs > 0) {
+ $changes{'othdom'} = 1;
+ }
+ }
+ } else {
+ my @stdfields = ('lastname','firstname','middlename','generation','permanentemail');
+ my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
+ if (@diffs > 0) {
+ $changes{'othdom'} = 1;
+ }
+ }
+ }
+ }
+ my %confighash = (
+ privacy => \%privacyhash,
+ );
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);
+ if ($putresult eq 'ok') {
+ if (keys(%changes) > 0) {
+ $resulttext = &mt('Changes made: ').'';
+ foreach my $key ('approval','othdom','priv','unpriv') {
+ if ($changes{$key}) {
+ $resulttext .= ''.$titles{$key}.':';
+ if ($key eq 'approval') {
+ if (keys(%{$privacyhash{$key}{instdom}})) {
+ $resulttext .= ''.$titles{'instdom'}.'';
+ foreach my $item (@items) {
+ $resulttext .= ''.$roles{$item}.': '.$titles{$privacyhash{$key}{instdom}{$item}}.' ';
+ }
+ $resulttext .= ' ';
+ }
+ if (keys(%{$privacyhash{$key}{extdom}})) {
+ $resulttext .= ''.$titles{'extdom'}.'';
+ foreach my $item (@items) {
+ $resulttext .= ''.$roles{$item}.': '.$titles{$privacyhash{$key}{extdom}{$item}}.' ';
+ }
+ $resulttext .= ' ';
+ }
+ } elsif ($key eq 'othdom') {
+ my @statuses;
+ if (ref($types) eq 'ARRAY') {
+ @statuses = @{$types};
+ }
+ if (ref($privacyhash{$key}) eq 'HASH') {
+ foreach my $status (@statuses,'default') {
+ if ($status eq 'default') {
+ $resulttext .= ''.$othertitle.': ';
+ } elsif (ref($usertypes) eq 'HASH') {
+ $resulttext .= ' '.$usertypes->{$status}.': ';
+ } else {
+ next;
+ }
+ if (ref($privacyhash{$key}{$status}) eq 'HASH') {
+ if (keys(%{$privacyhash{$key}{$status}})) {
+ $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$status}}))));
+ } else {
+ $resulttext .= &mt('none');
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ } else {
+ foreach my $item (@items) {
+ if (ref($privacyhash{$key}{$item}) eq 'HASH') {
+ $resulttext .= ''.$names{$item}.': ';
+ if (keys(%{$privacyhash{$key}{$item}})) {
+ $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$item}}))));
+ } else {
+ $resulttext .= &mt('none');
+ }
+ $resulttext .= ' ';
+ }
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ } else {
+ $resulttext = &mt('No changes made to user information settings');
+ }
+ } else {
+ $resulttext = ''.
+ &mt('An error occurred: [_1]',$putresult).' ';
+ }
+ return $resulttext;
+}
+
+sub modify_passwords {
+ my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
+ my ($resulttext,%current,%changes,%newvalues,@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',
+ expire => 'Password expiration (days)',
+ 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,
+ );
+ $staticdefaults{'min'} = $Apache::lonnet::passwdmin;
+ 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 (!ref($domconfig{passwords}) eq 'HASH') {
+ 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$/,@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 (!ref($domconfig{passwords}) eq 'HASH') {
+ 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 (!ref($domconfig{passwords}) eq 'HASH') {
+ 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 (!ref($domconfig{passwords}) eq 'HASH') {
+ 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 (!ref($domconfig{passwords}) eq 'HASH') {
+ 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 ($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 .= ''.$error.' ';
+ }
+ } 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','expire','numsaved') {
+ $env{'form.passwords_'.$rule} =~ s/^\s+|\s+$//g;
+ my $ruleok;
+ if ($rule eq 'expire') {
+ if (($env{'form.passwords_'.$rule} =~ /^\d+(|\.\d*)$/) &&
+ ($env{'form.passwords_'.$rule} ne '0')) {
+ $ruleok = 1;
+ }
+ } elsif ($rule eq 'min') {
+ if ($env{'form.passwords_'.$rule} =~ /^\d+$/) {
+ if ($env{'form.passwords_'.$rule} >= $Apache::lonnet::passwdmin) {
+ $ruleok = 1;
+ }
+ }
+ } elsif (($env{'form.passwords_'.$rule} =~ /^\d+$/) &&
+ ($env{'form.passwords_'.$rule} ne '0')) {
+ $ruleok = 1;
+ }
+ if ($ruleok) {
+ $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;
+ }
+ } else {
+ $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$/,@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 (!(ref($domconfig{passwords}) eq 'HASH')) {
+ 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: ').'';
+ foreach my $key ('reset','intauth','rules','crsownerchg') {
+ if ($changes{$key}) {
+ unless ($key eq 'intauth') {
+ $updateconf = 1;
+ }
+ $resulttext .= ''.$titles{$key}.':';
+ if ($key eq 'reset') {
+ if ($confighash{'passwords'}{'captcha'} eq 'original') {
+ $resulttext .= ''.&mt('CAPTCHA validation set to use: original CAPTCHA').' ';
+ } elsif ($confighash{'passwords'}{'captcha'} eq 'recaptcha') {
+ $resulttext .= ''.&mt('CAPTCHA validation set to use: reCAPTCHA').' '.
+ &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).' ';
+ if (ref($confighash{'passwords'}{'recaptchakeys'}) eq 'HASH') {
+ $resulttext .= &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'public'}).''.
+ &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'private'}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('No CAPTCHA validation').' ';
+ }
+ if ($confighash{'passwords'}{'resetlink'}) {
+ $resulttext .= ''.&mt('Reset link expiration set to [quant,_1,hour]',$confighash{'passwords'}{'resetlink'}).' ';
+ } else {
+ $resulttext .= ''.&mt('No reset link expiration set.').' '.
+ &mt('Will default to 2 hours').' ';
+ }
+ if (ref($confighash{'passwords'}{'resetcase'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetcase'}} == 0) {
+ $resulttext .= ''.&mt('User input for username and/or e-mail address not case sensitive for "Forgot Password" web form').' ';
+ } 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 .= ''.&mt('"Forgot Password" web form input for username and/or e-mail address is case-sensitive for: [_1]',$casesens).' ';
+ }
+ } else {
+ $resulttext .= ''.&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').' ';
+ }
+ if ($confighash{'passwords'}{'resetprelink'} eq 'either') {
+ $resulttext .= ''.&mt('Users can enter either a username or an e-mail address in "Forgot Password" web form').' ';
+ } else {
+ $resulttext .= ''.&mt('Users can enter both a username and an e-mail address in "Forgot Password" web form').' ';
+ }
+ 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 .= ''.&mt('Information required for new password form (by user type) set to: [_1]',$output).' ';
+ } else {
+ $resulttext .= ''.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').' ';
+ }
+ if (ref($confighash{'passwords'}{'resetemail'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetemail'}} > 0) {
+ $resulttext .= ''.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$confighash{'passwords'}{'resetemail'}})).' ';
+ } else {
+ $resulttext .= ''.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).' ';
+ }
+ if ($confighash{'passwords'}{'resetremove'}) {
+ $resulttext .= ''.&mt('Preamble to "Forgot Password" web form not shown').' ';
+ } else {
+ $resulttext .= ''.&mt('Preamble to "Forgot Password" web form is shown').' ';
+ }
+ if ($confighash{'passwords'}{'resetcustom'}) {
+ my $customlink = &Apache::loncommon::modal_link($confighash{'passwords'}{'resetcustom'},
+ &mt('custom text'),600,500,undef,undef,
+ undef,undef,'background-color:#ffffff');
+ $resulttext .= ''.&mt('Preamble to "Forgot Password" form includes: [_1]',$customlink).' ';
+ } else {
+ $resulttext .= ''.&mt('No custom text included in preamble to "Forgot Password" form').' ';
+ }
+ } 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 .= ''.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).' ';
+ }
+ } elsif ($key eq 'rules') {
+ foreach my $rule ('min','max','expire','numsaved') {
+ if ($confighash{'passwords'}{$rule} eq '') {
+ if ($rule eq 'min') {
+ $resulttext .= ''.&mt('[_1] not set.',$titles{$rule});
+ ' '.&mt('Default of [_1] will be used',
+ $Apache::lonnet::passwdmin).' ';
+ } else {
+ $resulttext .= ''.&mt('[_1] set to none',$titles{$rule}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).' ';
+ }
+ }
+ if (ref($confighash{'passwords'}{'chars'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'chars'}} > 0) {
+ 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',
+ );
+ my $needed = ''.
+ join(' ',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).
+ ' ';
+ $resulttext .= ''.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).' ';
+ } else {
+ $resulttext .= ''.&mt('[_1] set to none',$titles{'chars'}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('[_1] set to none',$titles{'chars'}).' ';
+ }
+ } elsif ($key eq 'crsownerchg') {
+ if (ref($confighash{'passwords'}{'crsownerchg'}) eq 'HASH') {
+ if ((@{$confighash{'passwords'}{'crsownerchg'}{'by'}} == 0) ||
+ (@{$confighash{'passwords'}{'crsownerchg'}{'for'}} == 0)) {
+ $resulttext .= ''.&mt('Course owner may not change student passwords.').' ';
+ } 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 .= ''.&mt('Course owner (with status: [_1]) may change passwords for students (with status: [_2]).',
+ $crsownerstr{'by'},$crsownerstr{'for'}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('Course owner may not change student passwords.').' ';
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ $resulttext .= ' ';
+ } 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 = ''.
+ &mt('An error occurred: [_1]',$putresult).' ';
+ }
+ if ($errors) {
+ $resulttext .= ''.&mt('The following errors occurred: ').'
';
+ }
+ return $resulttext;
+}
+
sub modify_usercreation {
my ($dom,%domconfig) = @_;
my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
@@ -12722,7 +16840,7 @@ sub modify_usercreation {
}
my @authen_contexts = ('author','course','domain');
- my @authtypes = ('int','krb4','krb5','loc');
+ my @authtypes = ('int','krb4','krb5','loc','lti');
my %authhash;
foreach my $item (@authen_contexts) {
my @authallowed = &Apache::loncommon::get_env_multiple('form.'.$item.'_auth');
@@ -13451,7 +17569,7 @@ sub modify_selfcreation {
$chgtext .= &mt('For self-created accounts verified by e-mail address, username is set as follows:').
'';
foreach my $status (@statuses) {
- if ($type eq 'default') {
+ if ($status eq 'default') {
$chgtext .= ''.$othertitle.' -- '.$options{$cancreate{'emailverified'}{$status}}.' ';
} else {
$chgtext .= ''.$usertypes{$status}.' -- '.$options{$cancreate{'emailverified'}{$status}}.' ';
@@ -13720,19 +17838,25 @@ sub modify_selfcreation {
}
sub process_captcha {
- my ($container,$changes,$newsettings,$current) = @_;
- return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
+ my ($container,$changes,$newsettings,$currsettings) = @_;
+ return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH'));
$newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
$newsettings->{'captcha'} = 'original';
}
- if ($current->{'captcha'} ne $newsettings->{'captcha'}) {
+ my %current;
+ if (ref($currsettings) eq 'HASH') {
+ %current = %{$currsettings};
+ }
+ if ($current{'captcha'} ne $newsettings->{'captcha'}) {
if ($container eq 'cancreate') {
if (ref($changes->{'cancreate'}) eq 'ARRAY') {
push(@{$changes->{'cancreate'}},'captcha');
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['captcha'];
}
+ } elsif ($container eq 'passwords') {
+ $changes->{'reset'} = 1;
} else {
$changes->{'captcha'} = 1;
}
@@ -13754,9 +17878,9 @@ sub process_captcha {
}
$newsettings->{'recaptchaversion'} = $newversion;
}
- if (ref($current->{'recaptchakeys'}) eq 'HASH') {
- $currpub = $current->{'recaptchakeys'}{'public'};
- $currpriv = $current->{'recaptchakeys'}{'private'};
+ if (ref($current{'recaptchakeys'}) eq 'HASH') {
+ $currpub = $current{'recaptchakeys'}{'public'};
+ $currpriv = $current{'recaptchakeys'}{'private'};
unless ($newsettings->{'captcha'} eq 'recaptcha') {
$newsettings->{'recaptchakeys'} = {
public => '',
@@ -13764,8 +17888,8 @@ sub process_captcha {
}
}
}
- if ($current->{'captcha'} eq 'recaptcha') {
- $currversion = $current->{'recaptchaversion'};
+ if ($current{'captcha'} eq 'recaptcha') {
+ $currversion = $current{'recaptchaversion'};
if ($currversion ne '2') {
$currversion = 1;
}
@@ -13777,6 +17901,8 @@ sub process_captcha {
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['recaptchaversion'];
}
+ } elsif ($container eq 'passwords') {
+ $changes->{'reset'} = 1;
} else {
$changes->{'recaptchaversion'} = 1;
}
@@ -13788,6 +17914,8 @@ sub process_captcha {
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['recaptchakeys'];
}
+ } elsif ($container eq 'passwords') {
+ $changes->{'reset'} = 1;
} else {
$changes->{'recaptchakeys'} = 1;
}
@@ -13903,8 +18031,8 @@ sub modify_defaults {
my ($resulttext,$mailmsgtxt,%newvalues,%changes,@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');
- my @authtypes = ('internal','krb4','krb5','localauth');
+ 'portal_def');
+ my @authtypes = ('internal','krb4','krb5','localauth','lti');
foreach my $item (@items) {
$newvalues{$item} = $env{'form.'.$item};
if ($item eq 'auth_def') {
@@ -13945,24 +18073,6 @@ sub modify_defaults {
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$/,@errors)) {
$newvalues{$item} = $domdefaults{$item};
@@ -13971,6 +18081,18 @@ sub modify_defaults {
}
$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,
);
@@ -14096,30 +18218,9 @@ sub modify_defaults {
krb4 => 'krb4',
krb5 => 'krb5',
localauth => 'loc',
+ lti => 'lti',
);
$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 .= ''.&mt('[_1] set to "[_2]"',$title->{$item},$value).' ';
$mailmsgtext .= "$title->{$item} set to $value\n";
@@ -14168,7 +18269,7 @@ sub modify_scantron {
my $custom = 'custom.tab';
my $default = 'default.tab';
my $servadm = $r->dir_config('lonAdmEMail');
- my ($configuserok,$author_ok,$switchserver) =
+ my ($configuserok,$author_ok,$switchserver) =
&config_check($dom,$confname,$servadm);
if ($env{'form.scantronformat.filename'} ne '') {
my $error;
@@ -14203,6 +18304,67 @@ sub modify_scantron {
if ($env{'form.scantronformat_del'}) {
$confhash{'scantron'}{'scantronformat'} = '';
$changes{'scantronformat'} = 1;
+ } else {
+ $confhash{'scantron'}{'scantronformat'} = $domconfig{'scantron'}{'scantronformat'};
+ }
+ }
+ }
+ my @options = ('hdr','pad','rem');
+ my @fields = &scantroncsv_fields();
+ my %titles = &scantronconfig_titles();
+ my @formats = &Apache::loncommon::get_env_multiple('form.scantronconfig');
+ my ($newdat,$currdat,%newcol,%currcol);
+ if (grep(/^dat$/,@formats)) {
+ $confhash{'scantron'}{config}{dat} = 1;
+ $newdat = 1;
+ } else {
+ $newdat = 0;
+ }
+ if (grep(/^csv$/,@formats)) {
+ my %bynum;
+ foreach my $field (@fields) {
+ if ($env{'form.scantronconfig_csv_'.$field} =~ /^(\d+)$/) {
+ my $posscol = $1;
+ if (($posscol < 20) && (!$bynum{$posscol})) {
+ $confhash{'scantron'}{config}{csv}{fields}{$field} = $posscol;
+ $bynum{$posscol} = $field;
+ $newcol{$field} = $posscol;
+ }
+ }
+ }
+ if (keys(%newcol)) {
+ foreach my $option (@options) {
+ if ($env{'form.scantroncsv_'.$option}) {
+ $confhash{'scantron'}{config}{csv}{options}{$option} = 1;
+ }
+ }
+ }
+ }
+ $currdat = 1;
+ if (ref($domconfig{'scantron'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {
+ unless (exists($domconfig{'scantron'}{'config'}{'dat'})) {
+ $currdat = 0;
+ }
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ %currcol = %{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}};
+ }
+ }
+ }
+ }
+ if ($currdat != $newdat) {
+ $changes{'config'} = 1;
+ } else {
+ foreach my $field (@fields) {
+ if ($currcol{$field} ne '') {
+ if ($currcol{$field} ne $newcol{$field}) {
+ $changes{'config'} = 1;
+ last;
+ }
+ } elsif ($newcol{$field} ne '') {
+ $changes{'config'} = 1;
+ last;
}
}
}
@@ -14213,22 +18375,57 @@ sub modify_scantron {
if (keys(%changes) > 0) {
if (ref($confhash{'scantron'}) eq 'HASH') {
$resulttext = &mt('Changes made:').'';
- if ($confhash{'scantron'}{'scantronformat'} eq '') {
- $resulttext .= ''.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).' ';
- } else {
- $resulttext .= ''.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).' ';
+ if ($changes{'scantronformat'}) {
+ if ($confhash{'scantron'}{'scantronformat'} eq '') {
+ $resulttext .= ''.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).' ';
+ } else {
+ $resulttext .= ''.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).' ';
+ }
+ }
+ if ($changes{'config'}) {
+ if (ref($confhash{'scantron'}{'config'}) eq 'HASH') {
+ if ($confhash{'scantron'}{'config'}{'dat'}) {
+ $resulttext .= ''.&mt('Bubblesheet data upload formats includes .dat format').' ';
+ }
+ if (ref($confhash{'scantron'}{'config'}{'csv'}) eq 'HASH') {
+ if (ref($confhash{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'fields'}})) {
+ $resulttext .= ''.&mt('Bubblesheet data upload formats includes .csv format, with following fields/column numbers supported:').'';
+ foreach my $field (@fields) {
+ if ($confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} ne '') {
+ my $showcol = $confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} + 1;
+ $resulttext .= ''.$titles{$field}.': '.$showcol.' ';
+ }
+ }
+ $resulttext .= ' ';
+ if (ref($confhash{'scantron'}{'config'}{'csv'}{'options'}) eq 'HASH') {
+ if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'options'}})) {
+ $resulttext .= ''.&mt('Bubblesheet data upload formats includes .csv format, with following options:').'';
+ foreach my $option (@options) {
+ if ($confhash{'scantron'}{'config'}{'csv'}{'options'}{$option} ne '') {
+ $resulttext .= ''.$titles{$option}.' ';
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ }
+ }
+ }
+ } else {
+ $resulttext .= ''.&mt('No bubblesheet data upload formats set -- will default to assuming .dat format').' ';
+ }
}
$resulttext .= ' ';
} else {
$resulttext = &mt('Changes made to bubblesheet format file.');
}
- $resulttext .= ' ';
&Apache::loncommon::devalidate_domconfig_cache($dom);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domainconfig'} = 1;
}
} else {
- $resulttext = &mt('No changes made to bubblesheet format file');
+ $resulttext = &mt('No changes made to bubblesheet format settings');
}
} else {
$resulttext = ''.
@@ -14238,8 +18435,8 @@ sub modify_scantron {
$resulttext = &mt('No changes made to bubblesheet format file');
}
if ($errors) {
- $resulttext .= &mt('The following errors occurred: ').'';
+ $resulttext .= ''.&mt('The following errors occurred: ').'
';
}
return $resulttext;
}
@@ -14514,6 +18711,10 @@ sub modify_coursecategories {
}
$resulttext .= ' ';
}
+ &Apache::lonnet::do_cache_new('cats',$dom,$cathash,3600);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'cats'} = 1;
+ }
}
$resulttext .= '';
if ($changes{'unauth'} || $changes{'auth'}) {
@@ -15060,7 +19261,6 @@ sub modify_coursedefaults {
$defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;
}
if ($currdef ne $newdef) {
- my $staticdef;
if ($item eq 'anonsurvey_threshold') {
unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
$changes{$item} = 1;
@@ -15076,11 +19276,12 @@ sub modify_coursedefaults {
my $texengine;
if ($env{'form.texengine'} =~ /^(MathJax|mimetex|tth)$/) {
$texengine = $env{'form.texengine'};
- if ($defaultshash{'coursedefaults'}{'texengine'} eq '') {
- unless ($texengine eq 'MathJax') {
+ my $currdef = $domconfig{'coursedefaults'}{'texengine'};
+ if ($currdef eq '') {
+ unless ($texengine eq $Apache::lonnet::deftex) {
$changes{'texengine'} = 1;
}
- } elsif ($defaultshash{'coursedefaults'}{'texengine'} ne $texengine) {
+ } elsif ($currdef ne $texengine) {
$changes{'texengine'} = 1;
}
}
@@ -15628,6 +19829,277 @@ sub modify_selfenrollment {
return $resulttext;
}
+sub modify_wafproxy {
+ my ($dom,$action,$lastactref,%domconfig) = @_;
+ my %servers = &Apache::lonnet::internet_dom_servers($dom);
+ my (%othercontrol,%canset,%values,%curralias,%currvalue,@warnings,%wafproxy,
+ %changes,%expirecache);
+ foreach my $server (sort(keys(%servers))) {
+ my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
+ if ($serverhome eq $server) {
+ my $serverdom = &Apache::lonnet::host_domain($server);
+ if ($serverdom eq $dom) {
+ $canset{$server} = 1;
+ }
+ }
+ }
+ if (ref($domconfig{'wafproxy'}) eq 'HASH') {
+ %{$values{$dom}} = ();
+ if (ref($domconfig{'wafproxy'}{'alias'}) eq 'HASH') {
+ %curralias = %{$domconfig{'wafproxy'}{'alias'}};
+ }
+ foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
+ $currvalue{$item} = $domconfig{'wafproxy'}{$item};
+ }
+ }
+ my $output;
+ if (keys(%canset)) {
+ %{$wafproxy{'alias'}} = ();
+ foreach my $key (sort(keys(%canset))) {
+ if ($env{'form.wafproxy_'.$dom}) {
+ $wafproxy{'alias'}{$key} = $env{'form.wafproxy_alias_'.$key};
+ $wafproxy{'alias'}{$key} =~ s/^\s+|\s+$//g;
+ if ($wafproxy{'alias'}{$key} ne $curralias{$key}) {
+ $changes{'alias'} = 1;
+ }
+ } else {
+ $wafproxy{'alias'}{$key} = '';
+ if ($curralias{$key}) {
+ $changes{'alias'} = 1;
+ }
+ }
+ if ($wafproxy{'alias'}{$key} eq '') {
+ if ($curralias{$key}) {
+ $expirecache{$key} = 1;
+ }
+ delete($wafproxy{'alias'}{$key});
+ }
+ }
+ unless (keys(%{$wafproxy{'alias'}})) {
+ delete($wafproxy{'alias'});
+ }
+ # Localization for values in %warn occus in &mt() calls separately.
+ my %warn = (
+ trusted => 'trusted IP range(s)',
+ vpnint => 'internal IP range(s) for VPN sessions(s)',
+ vpnext => 'IP range(s) for backend WAF connections',
+ );
+ foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
+ my $possible = $env{'form.wafproxy_'.$item};
+ $possible =~ s/^\s+|\s+$//g;
+ if ($possible ne '') {
+ if ($item eq 'remoteip') {
+ if ($possible =~ /^[mhn]$/) {
+ $wafproxy{$item} = $possible;
+ }
+ } elsif ($item eq 'ipheader') {
+ if ($wafproxy{'remoteip'} eq 'h') {
+ $wafproxy{$item} = $possible;
+ }
+ } elsif ($item eq 'sslopt') {
+ if ($possible =~ /^0|1$/) {
+ $wafproxy{$item} = $possible;
+ }
+ } else {
+ my (@ok,$count);
+ if (($item eq 'vpnint') || ($item eq 'vpnext')) {
+ unless ($env{'form.wafproxy_vpnaccess'}) {
+ $possible = '';
+ }
+ } elsif ($item eq 'trusted') {
+ unless ($wafproxy{'remoteip'} eq 'h') {
+ $possible = '';
+ }
+ }
+ unless ($possible eq '') {
+ $possible =~ s/[\r\n]+/\s/g;
+ $possible =~ s/\s*-\s*/-/g;
+ $possible =~ s/\s+/,/g;
+ }
+ $count = 0;
+ if ($possible ne '') {
+ foreach my $poss (split(/\,/,$possible)) {
+ $count ++;
+ if (&validate_ip_pattern($poss)) {
+ push(@ok,$poss);
+ }
+ }
+ if (@ok) {
+ $wafproxy{$item} = join(',',@ok);
+ }
+ my $diff = $count - scalar(@ok);
+ if ($diff) {
+ push(@warnings,''.
+ &mt('[quant,_1,IP] invalid and excluded from saved value for [_2]',
+ $diff,$warn{$item}).
+ ' ');
+ }
+ }
+ }
+ if ($wafproxy{$item} ne $currvalue{$item}) {
+ $changes{$item} = 1;
+ }
+ } elsif ($currvalue{$item}) {
+ $changes{$item} = 1;
+ }
+ }
+ } else {
+ if (keys(%curralias)) {
+ $changes{'alias'} = 1;
+ }
+ if (keys(%currvalue)) {
+ foreach my $key (keys(%currvalue)) {
+ $changes{$key} = 1;
+ }
+ }
+ }
+ if (keys(%changes)) {
+ my %defaultshash = (
+ wafproxy => \%wafproxy,
+ );
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
+ $dom);
+ if ($putresult eq 'ok') {
+ my $cachetime = 24*60*60;
+ my (%domdefaults,$updatedomdefs);
+ foreach my $item ('ipheader','trusted','vpnint','vpnext','sslopt') {
+ if ($changes{$item}) {
+ unless ($updatedomdefs) {
+ %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
+ $updatedomdefs = 1;
+ }
+ if ($wafproxy{$item}) {
+ $domdefaults{'waf_'.$item} = $wafproxy{$item};
+ } elsif (exists($domdefaults{'waf_'.$item})) {
+ delete($domdefaults{'waf_'.$item});
+ }
+ }
+ }
+ if ($updatedomdefs) {
+ &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'domdefaults'} = 1;
+ }
+ }
+ if ((exists($wafproxy{'alias'})) || (keys(%expirecache))) {
+ my %updates = %expirecache;
+ foreach my $key (keys(%expirecache)) {
+ &Apache::lonnet::devalidate_cache_new('proxyalias',$key);
+ }
+ if (ref($wafproxy{'alias'}) eq 'HASH') {
+ my $cachetime = 24*60*60;
+ foreach my $key (keys(%{$wafproxy{'alias'}})) {
+ $updates{$key} = 1;
+ &Apache::lonnet::do_cache_new('proxyalias',$key,$wafproxy{'alias'}{$key},
+ $cachetime);
+ }
+ }
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'proxyalias'} = \%updates;
+ }
+ }
+ $output = &mt('Changes were made to Web Application Firewall/Reverse Proxy').'';
+ foreach my $item ('alias','remoteip','ipheader','trusted','vpnint','vpnext','sslopt') {
+ if ($changes{$item}) {
+ if ($item eq 'alias') {
+ my $numaliased = 0;
+ if (ref($wafproxy{'alias'}) eq 'HASH') {
+ my $shown;
+ if (keys(%{$wafproxy{'alias'}})) {
+ foreach my $server (sort(keys(%{$wafproxy{'alias'}}))) {
+ $shown .= ''.&mt('[_1] aliased by [_2]',
+ &Apache::lonnet::hostname($server),
+ $wafproxy{'alias'}{$server}).' ';
+ $numaliased ++;
+ }
+ if ($numaliased) {
+ $output .= ''.&mt('Aliases for hostnames set to: [_1]',
+ '').' ';
+ }
+ }
+ }
+ unless ($numaliased) {
+ $output .= ''.&mt('Aliases deleted for hostnames').' ';
+ }
+ } else {
+ if ($item eq 'remoteip') {
+ my %ip_methods = &remoteip_methods();
+ if ($wafproxy{$item} =~ /^[mh]$/) {
+ $output .= ''.&mt("Method for determining user's IP set to: [_1]",
+ $ip_methods{$wafproxy{$item}}).' ';
+ } else {
+ if (($env{'form.wafproxy_'.$dom}) && (ref($wafproxy{'alias'}) eq 'HASH')) {
+ $output .= ''.&mt("No method in use to get user's real IP (will report IP used by WAF).").
+ ' ';
+ } else {
+ $output .= ''.&mt('WAF/Reverse Proxy not in use').' ';
+ }
+ }
+ } elsif ($item eq 'ipheader') {
+ if ($wafproxy{$item}) {
+ $output .= ''.&mt('Request header with remote IP set to: [_1]',
+ $wafproxy{$item}).' ';
+ } else {
+ $output .= ''.&mt('Request header with remote IP deleted').' ';
+ }
+ } elsif ($item eq 'trusted') {
+ if ($wafproxy{$item}) {
+ $output .= ''.&mt('Trusted IP range(s) set to: [_1]',
+ $wafproxy{$item}).' ';
+ } else {
+ $output .= ''.&mt('Trusted IP range(s) deleted').' ';
+ }
+ } elsif ($item eq 'vpnint') {
+ if ($wafproxy{$item}) {
+ $output .= ''.&mt('Internal IP Range(s) for VPN sessions set to: [_1]',
+ $wafproxy{$item}).' ';
+ } else {
+ $output .= ''.&mt('Internal IP Range(s) for VPN sessions deleted').' ';
+ }
+ } elsif ($item eq 'vpnext') {
+ if ($wafproxy{$item}) {
+ $output .= ''.&mt('IP Range(s) for backend WAF connections set to: [_1]',
+ $wafproxy{$item}).' ';
+ } else {
+ $output .= ''.&mt('IP Range(s) for backend WAF connections deleted').' ';
+ }
+ } elsif ($item eq 'sslopt') {
+ if ($wafproxy{$item}) {
+ $output .= ''.&mt('WAF/Reverse Proxy expected to forward requests to https on LON-CAPA node, regardless of original protocol in web browser (http or https).').' ';
+ } else {
+ $output .= ''.&mt('WAF/Reverse Proxy expected to preserve original protocol in web browser (either http or https) when forwarding to LON-CAPA node.').' ';
+ }
+ }
+ }
+ }
+ }
+ } else {
+ $output = ''.
+ &mt('An error occurred: [_1]',$putresult).' ';
+ }
+ } elsif (keys(%canset)) {
+ $output = &mt('No changes made to Web Application Firewall/Reverse Proxy settings');
+ }
+ if (@warnings) {
+ $output .= ' '.&mt('Warnings:').''.
+ join("\n",@warnings).' ';
+ }
+ return $output;
+}
+
+sub validate_ip_pattern {
+ my ($pattern) = @_;
+ if ($pattern =~ /^([^-]+)\-([^-]+)$/) {
+ my ($start,$end) = ($1,$2);
+ if ((&Net::CIDR::cidrvalidate($start)) && (&Net::CIDR::cidrvalidate($end))) {
+ return 1;
+ }
+ } elsif (&Net::CIDR::cidrvalidate($pattern)) {
+ return 1;
+ }
+ return
+}
+
sub modify_usersessions {
my ($dom,$lastactref,%domconfig) = @_;
my @hostingtypes = ('version','excludedomain','includedomain');
@@ -15795,6 +20267,7 @@ sub modify_usersessions {
}
}
$defaultshash{'usersessions'}{'offloadnow'} = {};
+ $defaultshash{'usersessions'}{'offloadoth'} = {};
my @offloadnow = &Apache::loncommon::get_env_multiple('form.offloadnow');
my @okoffload;
if (@offloadnow) {
@@ -15811,6 +20284,22 @@ sub modify_usersessions {
}
}
}
+ my @offloadoth = &Apache::loncommon::get_env_multiple('form.offloadoth');
+ my @okoffloadoth;
+ if (@offloadoth) {
+ foreach my $server (@offloadoth) {
+ if (&Apache::lonnet::hostname($server) ne '') {
+ unless (grep(/^\Q$server\E$/,@okoffloadoth)) {
+ push(@okoffloadoth,$server);
+ }
+ }
+ }
+ if (@okoffloadoth) {
+ foreach my $lonhost (@okoffloadoth) {
+ $defaultshash{'usersessions'}{'offloadoth'}{$lonhost} = 1;
+ }
+ }
+ }
if (ref($domconfig{'usersessions'}) eq 'HASH') {
if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') {
if (ref($changes{'spares'}) eq 'HASH') {
@@ -15821,26 +20310,38 @@ sub modify_usersessions {
} else {
$savespares = 1;
}
- if (ref($domconfig{'usersessions'}{'offloadnow'}) eq 'HASH') {
- foreach my $lonhost (keys(%{$domconfig{'usersessions'}{'offloadnow'}})) {
- unless ($defaultshash{'usersessions'}{'offloadnow'}{$lonhost}) {
- $changes{'offloadnow'} = 1;
- last;
- }
- }
- unless ($changes{'offloadnow'}) {
- foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) {
- unless ($domconfig{'usersessions'}{'offloadnow'}{$lonhost}) {
- $changes{'offloadnow'} = 1;
+ foreach my $offload ('offloadnow','offloadoth') {
+ if (ref($domconfig{'usersessions'}{$offload}) eq 'HASH') {
+ foreach my $lonhost (keys(%{$domconfig{'usersessions'}{$offload}})) {
+ unless ($defaultshash{'usersessions'}{$offload}{$lonhost}) {
+ $changes{$offload} = 1;
last;
}
}
- }
- } elsif (@okoffload) {
+ unless ($changes{$offload}) {
+ foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{$offload}})) {
+ unless ($domconfig{'usersessions'}{$offload}{$lonhost}) {
+ $changes{$offload} = 1;
+ last;
+ }
+ }
+ }
+ } else {
+ if (($offload eq 'offloadnow') && (@okoffload)) {
+ $changes{'offloadnow'} = 1;
+ }
+ if (($offload eq 'offloadoth') && (@okoffloadoth)) {
+ $changes{'offloadoth'} = 1;
+ }
+ }
+ }
+ } else {
+ if (@okoffload) {
$changes{'offloadnow'} = 1;
}
- } elsif (@okoffload) {
- $changes{'offloadnow'} = 1;
+ if (@okoffloadoth) {
+ $changes{'offloadoth'} = 1;
+ }
}
my $nochgmsg = &mt('No changes made to settings for user session hosting/offloading.');
if ((keys(%changes) > 0) || ($savespares)) {
@@ -15857,6 +20358,9 @@ sub modify_usersessions {
if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
$domdefaults{'offloadnow'} = $defaultshash{'usersessions'}{'offloadnow'};
}
+ if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {
+ $domdefaults{'offloadoth'} = $defaultshash{'usersessions'}{'offloadoth'};
+ }
}
my $cachetime = 24*60*60;
&Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
@@ -15897,14 +20401,18 @@ sub modify_usersessions {
} else {
foreach my $type (@{$types{$prefix}}) {
if (defined($changes{$prefix}{$type})) {
- my $newvalue;
+ my ($newvalue,$notinuse);
if (ref($defaultshash{'usersessions'}) eq 'HASH') {
if (ref($defaultshash{'usersessions'}{$prefix})) {
if ($type eq 'version') {
$newvalue = $defaultshash{'usersessions'}{$prefix}{$type};
- } elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
- if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
- $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
+ } else {
+ if (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
+ if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
+ $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
+ }
+ } else {
+ $notinuse = 1;
}
}
}
@@ -15912,12 +20420,14 @@ sub modify_usersessions {
if ($newvalue eq '') {
if ($type eq 'version') {
$resulttext .= ''.&mt('[_1] set to: off',$lt{$type}).' ';
+ } elsif ($notinuse) {
+ $resulttext .= ''.&mt('[_1] set to: not in use',$lt{$type}).' ';
} else {
$resulttext .= ''.&mt('[_1] set to: none',$lt{$type}).' ';
}
} else {
if ($type eq 'version') {
- $newvalue .= ' '.&mt('(or later)');
+ $newvalue .= ' '.&mt('(or later)');
}
$resulttext .= ''.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).' ';
}
@@ -15930,16 +20440,31 @@ sub modify_usersessions {
if ($changes{'offloadnow'}) {
if (ref($defaultshash{'usersessions'}{'offloadnow'}) eq 'HASH') {
if (keys(%{$defaultshash{'usersessions'}{'offloadnow'}}) > 0) {
- $resulttext .= ''.&mt('Switch active users on next access, for server(s):').'';
+ $resulttext .= ''.&mt('Switch any active user on next access, for server(s):').'';
foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadnow'}}))) {
$resulttext .= ''.$lonhost.' ';
}
$resulttext .= ' ';
} else {
- $resulttext .= ' '.&mt('No servers now set to switch active users on next access.');
+ $resulttext .= ' '.&mt('No servers now set to switch any active user on next access.');
}
} else {
- $resulttext .= ' '.&mt('No servers now set to switch active users on next access.').' ';
+ $resulttext .= ''.&mt('No servers now set to switch any active user on next access.').' ';
+ }
+ }
+ if ($changes{'offloadoth'}) {
+ if (ref($defaultshash{'usersessions'}{'offloadoth'}) eq 'HASH') {
+ if (keys(%{$defaultshash{'usersessions'}{'offloadoth'}}) > 0) {
+ $resulttext .= ''.&mt('Switch other institutions on next access, for server(s):').'';
+ foreach my $lonhost (sort(keys(%{$defaultshash{'usersessions'}{'offloadoth'}}))) {
+ $resulttext .= ''.$lonhost.' ';
+ }
+ $resulttext .= ' ';
+ } else {
+ $resulttext .= ' '.&mt('No servers now set to switch other institutions on next access.');
+ }
+ } else {
+ $resulttext .= ' '.&mt('No servers now set to switch other institutions on next access.').' ';
}
}
$resulttext .= ' ';
@@ -15985,12 +20510,17 @@ sub modify_ssl {
if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
$value = $env{'form.'.$prefix.'_'.$type};
}
- if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
- if ($domconfig{$action}{$prefix}{$type} ne '') {
- if ($value ne $domconfig{$action}{$prefix}{$type}) {
+ if (ref($domconfig{$action}) eq 'HASH') {
+ if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
+ if ($domconfig{$action}{$prefix}{$type} ne '') {
+ if ($value ne $domconfig{$action}{$prefix}{$type}) {
+ $changes{$prefix}{$type} = 1;
+ }
+ $defaultshash{$action}{$prefix}{$type} = $value;
+ } else {
+ $defaultshash{$action}{$prefix}{$type} = $value;
$changes{$prefix}{$type} = 1;
}
- $defaultshash{$action}{$prefix}{$type} = $value;
} else {
$defaultshash{$action}{$prefix}{$type} = $value;
$changes{$prefix}{$type} = 1;
@@ -16060,6 +20590,17 @@ sub modify_ssl {
}
}
}
+ if (keys(%changes)) {
+ foreach my $prefix (keys(%changes)) {
+ if (ref($changes{$prefix}) eq 'HASH') {
+ if (scalar(keys(%{$changes{$prefix}})) == 0) {
+ delete($changes{$prefix});
+ }
+ } else {
+ delete($changes{$prefix});
+ }
+ }
+ }
my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
if (keys(%changes) > 0) {
my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
@@ -16070,10 +20611,10 @@ sub modify_ssl {
$domdefaults{'replication'} = $defaultshash{$action}{'replication'};
}
if (ref($defaultshash{$action}{'connto'}) eq 'HASH') {
- $domdefaults{'connto'} = $domconfig{$action}{'connto'};
+ $domdefaults{'connto'} = $defaultshash{$action}{'connto'};
}
if (ref($defaultshash{$action}{'connfrom'}) eq 'HASH') {
- $domdefaults{'connfrom'} = $domconfig{$action}{'connfrom'};
+ $domdefaults{'connfrom'} = $defaultshash{$action}{'connfrom'};
}
}
my $cachetime = 24*60*60;
@@ -16089,18 +20630,24 @@ sub modify_ssl {
$resulttext .= ' '.$titles{$prefix}.'';
foreach my $type (@{$types{$prefix}}) {
if (defined($changes{$prefix}{$type})) {
- my $newvalue;
+ my ($newvalue,$notinuse);
if (ref($defaultshash{$action}) eq 'HASH') {
if (ref($defaultshash{$action}{$prefix})) {
if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
$newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
- } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
- if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
- $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
+ } else {
+ if (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
+ if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
+ $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
+ }
+ } else {
+ $notinuse = 1;
}
}
}
- if ($newvalue eq '') {
+ if ($notinuse) {
+ $resulttext .= ''.&mt('[_1] set to: not in use',$titles{$type}).' ';
+ } elsif ($newvalue eq '') {
$resulttext .= ''.&mt('[_1] set to: none',$titles{$type}).' ';
} else {
$resulttext .= ''.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).' ';
@@ -16214,17 +20761,21 @@ sub modify_trust {
$resulttext .= ''.$lt{$prefix}.'';
foreach my $type (@types) {
if (defined($changes{$prefix}{$type})) {
- my $newvalue;
+ my ($newvalue,$notinuse);
if (ref($defaultshash{'trust'}) eq 'HASH') {
if (ref($defaultshash{'trust'}{$prefix})) {
if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
$newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
}
+ } else {
+ $notinuse = 1;
}
}
}
- if ($newvalue eq '') {
+ if ($notinuse) {
+ $resulttext .= ''.&mt('[_1] set to: not in use',$lt{$type}).' ';
+ } elsif ($newvalue eq '') {
$resulttext .= ''.&mt('[_1] set to: none',$lt{$type}).' ';
} else {
$resulttext .= ''.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).' ';
@@ -16259,12 +20810,12 @@ sub modify_loadbalancing {
my @sparestypes = ('primary','default');
my %typetitles = &sparestype_titles();
my $resulttext;
- my (%currbalancer,%currtargets,%currrules,%existing);
+ my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
}
&get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
- \%currtargets,\%currrules);
+ \%currtargets,\%currrules,\%currcookies);
my ($saveloadbalancing,%defaultshash,%changes);
my ($alltypes,$othertypes,$titles) =
&loadbalancing_titles($dom,$intdom,$usertypes,$types);
@@ -16316,6 +20867,18 @@ sub modify_loadbalancing {
}
$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
}
+ if ($env{'form.loadbalancing_cookie_'.$i}) {
+ $defaultshash{'loadbalancing'}{$balancer}{'cookie'} = 1;
+ if (exists($currbalancer{$balancer})) {
+ unless ($currcookies{$balancer}) {
+ $changes{'curr'}{$balancer}{'cookie'} = 1;
+ }
+ }
+ } elsif (exists($currbalancer{$balancer})) {
+ if ($currcookies{$balancer}) {
+ $changes{'curr'}{$balancer}{'cookie'} = 1;
+ }
+ }
if (ref($currtargets{$balancer}) eq 'HASH') {
foreach my $sparetype (@sparestypes) {
if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
@@ -16469,24 +21032,28 @@ sub modify_loadbalancing {
}
}
}
- if (keys(%toupdate)) {
- my %thismachine;
- my $updatedhere;
- my $cachetime = 60*60*24;
- map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
- foreach my $lonhost (keys(%toupdate)) {
- if ($thismachine{$lonhost}) {
- unless ($updatedhere) {
- &Apache::lonnet::do_cache_new('loadbalancing',$dom,
- $defaultshash{'loadbalancing'},
- $cachetime);
- $updatedhere = 1;
- }
- } else {
- my $cachekey = &escape('loadbalancing').':'.&escape($dom);
- &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
- }
+ if ($changes{'curr'}{$balancer}{'cookie'}) {
+ $resulttext .= ''.&mt('Load Balancer: [_1] -- cookie use enabled',
+ $balancer).' ';
+ }
+ }
+ }
+ if (keys(%toupdate)) {
+ my %thismachine;
+ my $updatedhere;
+ my $cachetime = 60*60*24;
+ map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
+ foreach my $lonhost (keys(%toupdate)) {
+ if ($thismachine{$lonhost}) {
+ unless ($updatedhere) {
+ &Apache::lonnet::do_cache_new('loadbalancing',$dom,
+ $defaultshash{'loadbalancing'},
+ $cachetime);
+ $updatedhere = 1;
}
+ } else {
+ my $cachekey = &escape('loadbalancing').':'.&escape($dom);
+ &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
}
}
}
@@ -16698,12 +21265,12 @@ sub lonbalance_targets_js {
}
push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
$allinsttypes = join("','",@alltypes);
- my (%currbalancer,%currtargets,%currrules,%existing);
+ my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
if (ref($settings) eq 'HASH') {
%existing = %{$settings};
}
&get_loadbalancers_config($servers,\%existing,\%currbalancer,
- \%currtargets,\%currrules);
+ \%currtargets,\%currrules,\%currcookies);
my $balancers = join("','",sort(keys(%currbalancer)));
return <<"END";
@@ -16983,6 +21550,7 @@ function balancerChange(balnum,baltotal,
END
}
+
sub new_spares_js {
my @sparestypes = ('primary','default');
my $types = join("','",@sparestypes);
@@ -17056,7 +21624,7 @@ function updateNewSpares(formname,lonhos
function checkNewSpares(lonhost,type) {
var newSpare = document.getElementById('newspare_'+type+'_'+lonhost);
var chosen = newSpare.options[newSpare.selectedIndex].value;
- if (chosen != '') {
+ if (chosen != '') {
var othertype;
var othernewSpare;
if (type == 'primary') {
@@ -17190,7 +21758,7 @@ function toggleDisplay(domForm,caller) {
var dispval = 'block';
var selfcreateRegExp = /^cancreate_emailverified/;
if (caller == 'emailoptions') {
- optionsElement = domForm.cancreate_email;
+ optionsElement = domForm.cancreate_email;
}
if (caller == 'studentsubmission') {
optionsElement = domForm.postsubmit;
@@ -17245,14 +21813,23 @@ sub devalidate_remote_domconfs {
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %thismachine;
map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
- my @posscached = ('domainconfig','domdefaults','ltitools','usersessions','directorysrch');
+ my @posscached = ('domainconfig','domdefaults','ltitools','usersessions',
+ 'directorysrch','passwdconf','cats','proxyalias');
if (keys(%servers)) {
foreach my $server (keys(%servers)) {
next if ($thismachine{$server});
my @cached;
foreach my $name (@posscached) {
if ($cachekeys->{$name}) {
- push(@cached,&escape($name).':'.&escape($dom));
+ if ($name eq 'proxyalias') {
+ if (ref($cachekeys->{$name}) eq 'HASH') {
+ foreach my $key (keys(%{$cachekeys->{$name}})) {
+ push(@cached,&escape($name).':'.&escape($key));
+ }
+ }
+ } else {
+ push(@cached,&escape($name).':'.&escape($dom));
+ }
}
}
if (@cached) {