--- loncom/interface/domainprefs.pm 2022/02/14 02:48:46 1.405 +++ loncom/interface/domainprefs.pm 2023/06/01 18:09:59 1.424 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.405 2022/02/14 02:48:46 raeburn Exp $ +# $Id: domainprefs.pm,v 1.424 2023/06/01 18:09:59 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -167,6 +167,7 @@ use Apache::lonmsg(); use Apache::lonconfigsettings; use Apache::lonuserutils(); use Apache::loncoursequeueadmin(); +use Apache::courseprefs(); use LONCAPA qw(:DEFAULT :match); use LONCAPA::Enrollment; use LONCAPA::lonauthcgi(); @@ -177,6 +178,7 @@ use DateTime::TimeZone; use DateTime::Locale; use Time::HiRes qw( sleep ); use Net::CIDR; +use Crypt::CBC; my $registered_cleanup; my $modified_urls; @@ -220,17 +222,27 @@ sub handler { 'serverstatuses','requestcourses','helpsettings', 'coursedefaults','usersessions','loadbalancing', 'requestauthor','selfenrollment','inststatus', - 'ltitools','ssl','trust','lti','ltisec','privacy','passwords', - 'proctoring','wafproxy','ipaccess'],$dom); + 'ltitools','toolsec','ssl','trust','lti','ltisec', + 'privacy','passwords','proctoring','wafproxy','ipaccess'],$dom); my %encconfig = &Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring','linkprot'],$dom,undef,1); + my ($checked_is_home,$is_home); if (ref($domconfig{'ltitools'}) eq 'HASH') { if (ref($encconfig{'ltitools'}) eq 'HASH') { + my $home = &Apache::lonnet::domain($dom,'primary'); + unless (($home eq 'no_host') || ($home eq '')) { + my @ids=&Apache::lonnet::current_machine_ids(); + if (grep(/^\Q$home\E$/,@ids)) { + $is_home = 1; + } + } + $checked_is_home = 1; foreach my $id (keys(%{$domconfig{'ltitools'}})) { if ((ref($domconfig{'ltitools'}{$id}) eq 'HASH') && (ref($encconfig{'ltitools'}{$id}) eq 'HASH')) { - foreach my $item ('key','secret') { - $domconfig{'ltitools'}{$id}{$item} = $encconfig{'ltitools'}{$id}{$item}; + $domconfig{'ltitools'}{$id}{'key'} = $encconfig{'ltitools'}{$id}{'key'}; + if (($is_home) && ($phase eq 'process')) { + $domconfig{'ltitools'}{$id}{'secret'} = $encconfig{'ltitools'}{$id}{'secret'}; } } } @@ -238,24 +250,38 @@ sub handler { } if (ref($domconfig{'lti'}) eq 'HASH') { if (ref($encconfig{'lti'}) eq 'HASH') { + unless ($checked_is_home) { + my $home = &Apache::lonnet::domain($dom,'primary'); + unless (($home eq 'no_host') || ($home eq '')) { + my @ids=&Apache::lonnet::current_machine_ids(); + if (grep(/^\Q$home\E$/,@ids)) { + $is_home = 1; + } + } + $checked_is_home = 1; + } foreach my $id (keys(%{$domconfig{'lti'}})) { if ((ref($domconfig{'lti'}{$id}) eq 'HASH') && (ref($encconfig{'lti'}{$id}) eq 'HASH')) { - foreach my $item ('key','secret') { - $domconfig{'lti'}{$id}{$item} = $encconfig{'lti'}{$id}{$item}; + $domconfig{'lti'}{$id}{'key'} = $encconfig{'lti'}{$id}{'key'}; + if (($is_home) && ($phase eq 'process')) { + $domconfig{'lti'}{$id}{'secret'} = $encconfig{'lti'}{$id}{'secret'}; } } } } } if (ref($domconfig{'ltisec'}) eq 'HASH') { - if (ref($domconfig{'ltisec'}{'prot'}) eq 'HASH') { + if (ref($domconfig{'ltisec'}{'linkprot'}) eq 'HASH') { if (ref($encconfig{'linkprot'}) eq 'HASH') { - foreach my $id (keys(%{$domconfig{'ltisec'}{'prot'}})) { - if ((ref($domconfig{'ltisec'}{'prot'}{$id}) eq 'HASH') && + foreach my $id (keys(%{$domconfig{'ltisec'}{'linkprot'}})) { + unless ($id =~ /^\d+$/) { + delete($domconfig{'ltisec'}{'linkprot'}{$id}); + } + if ((ref($domconfig{'ltisec'}{'linkprot'}{$id}) eq 'HASH') && (ref($encconfig{'linkprot'}{$id}) eq 'HASH')) { foreach my $item ('key','secret') { - $domconfig{'ltisec'}{'prot'}{$id}{$item} = $encconfig{'linkprot'}{$id}{$item}; + $domconfig{'ltisec'}{'linkprot'}{$id}{$item} = $encconfig{'linkprot'}{$id}{$item}; } } } @@ -324,7 +350,9 @@ sub handler { header => [{col1 => 'Setting', col2 => 'Value'}, {col1 => 'Institutional user types', - col2 => 'Name displayed'}], + col2 => 'Name displayed'}, + {col1 => 'Mapping for missing usernames via standard log-in', + col2 => 'Rules in use'}], print => \&print_defaults, modify => \&modify_defaults, }, @@ -354,7 +382,7 @@ sub handler { modify => \&modify_passwords, }, 'quotas' => - { text => 'Blogs, personal web pages, webDAV/quotas, portfolios', + { text => 'Blogs, personal pages/timezones, webDAV/quotas, portfolio', help => 'Domain_Configuration_Quotas', header => [{col1 => 'User affiliation', col2 => 'Available tools', @@ -579,8 +607,12 @@ sub handler { 'ltitools' => {text => 'External Tools (LTI)', help => 'Domain_Configuration_LTI_Tools', - header => [{col1 => 'Setting', - col2 => 'Value',}], + header => [{col1 => 'Encryption of shared secrets', + col2 => 'Settings'}, + {col1 => 'Rules for shared secrets', + col2 => 'Settings'}, + {col1 => 'Providers', + col2 => 'Settings',}], print => \&print_ltitools, modify => \&modify_ltitools, }, @@ -637,7 +669,7 @@ sub handler { col2 => 'Settings'}, {col1 => 'Rules for shared secrets', col2 => 'Settings'}, - {col1 => 'Link Protectors (domain)', + {col1 => 'Link Protectors', col2 => 'Settings'}, {col1 => 'Consumers', col2 => 'Settings'},], @@ -888,9 +920,9 @@ sub print_config_box { &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full, \@templateroles); } elsif ($action eq 'ltitools') { - $output .= <itools_javascript($settings); + $output .= &Apache::lonconfigsettings::ltitools_javascript($settings); } elsif ($action eq 'lti') { - $output .= &passwords_javascript('secrets')."\n". + $output .= &passwords_javascript('ltisecrets')."\n". <i_javascript($dom,$settings); } elsif ($action eq 'proctoring') { $output .= &proctoring_javascript($settings); @@ -945,7 +977,8 @@ 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 'privacy') || ($action eq 'wafproxy') || ($action eq 'lti')) { + ($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'wafproxy') || + ($action eq 'lti') || ($action eq 'ltitools')) { $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'passwords') { $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal); @@ -980,8 +1013,9 @@ 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 'privacy') || ($action eq 'passwords') || ($action eq 'lti')) { + ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults') || + ($action eq 'privacy') || ($action eq 'passwords') || ($action eq 'lti') || + ($action eq 'ltitools')) { if ($action eq 'coursecategories') { $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal); $colspan = ' colspan="2"'; @@ -1068,8 +1102,8 @@ sub print_config_box { } $rowtotal ++; } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') || - ($action eq 'defaults') || ($action eq 'directorysrch') || - ($action eq 'helpsettings') || ($action eq 'wafproxy')) { + ($action eq 'directorysrch') || ($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); @@ -1272,8 +1306,7 @@ 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 'proctoring') || - ($action eq 'ipaccess')) { + ($action eq 'proctoring') || ($action eq 'ipaccess')) { $output .= $item->{'print'}->($dom,$settings,\$rowtotal); } } @@ -1623,13 +1656,13 @@ sub print_login { '
'.$choices{'hostid'}.' | '. ''.$choices{'samllanding'}.' | '. ''.$choices{'samloptions'}.' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
'.$domservers{$lonhost}.' | '. ''. ' | '.
- '
'. + '
| ';
@@ -2365,7 +2411,7 @@ sub print_quotas {
@options = ('norequest','approval','automatic');
%titles = &authorrequest_titles();
} else {
- @usertools = ('aboutme','blog','webdav','portfolio');
+ @usertools = ('aboutme','blog','webdav','portfolio','timezone');
%titles = &tool_titles();
}
if (ref($types) eq 'ARRAY') {
@@ -2469,9 +2515,12 @@ sub print_quotas {
}
} else {
my $checked = 'checked="checked" ';
+ if ($item eq 'timezone') {
+ $checked = '';
+ }
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
- if ($settings->{$item}->{$type} == 0) {
+ if (!$settings->{$item}->{$type}) {
$checked = '';
} elsif ($settings->{$item}->{$type} == 1) {
$checked = 'checked="checked" ';
@@ -3410,8 +3459,17 @@ ENDSCRIPT
sub lti_javascript {
my ($dom,$settings) = @_;
my $togglejs = <i_toggle_js($dom);
+ my $linkprot_js = &Apache::courseprefs::linkprot_javascript();
unless (ref($settings) eq 'HASH') {
- return $togglejs;
+ return $togglejs.'
+
+';
}
my (%ordered,$total,%jstext);
$total = scalar(keys(%{$settings}));
@@ -3473,6 +3531,9 @@ $jstext
}
return;
}
+
+$linkprot_js
+
// ]]>
@@ -3696,124 +3757,6 @@ function toggleLTI(form,setting,item) {
return;
}
-function toggleLTIEncKey(form) {
- var shownhosts = new Array();
- var hiddenhosts = new Array();
- var forcourse = new Array($course_servers);
- var fromdomain = '$primary';
- var crsradio = form.elements['ltisec_crslinkprot'];
- if (crsradio.length) {
- for (var i=0; i'
- .''.(' 'x2).
- ' | '.
- ''.
- ''.
- '';
- my (%checkedfields,%rolemaps,$userincdom);
- if (ref($settings->{$item}) eq 'HASH') {
- if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
- %checkedfields = %{$settings->{$item}->{'fields'}};
- }
- $userincdom = $settings->{$item}->{'incdom'};
- if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
- %rolemaps = %{$settings->{$item}->{'roles'}};
- $checkedfields{'roles'} = 1;
- }
- }
- $datatable .= ''.
- '';
- my %courseconfig;
- if (ref($settings->{$item}) eq 'HASH') {
- if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
- %courseconfig = %{$settings->{$item}->{'crsconf'}};
}
}
- $datatable .= ''.
- ' | '."\n".
- ''."\n".
- ' '."\n".
- ''.&mt('Add').' | '."\n".
- ''.
- ''.
- ''.
- '';
- $datatable .= ''.
- ''.
- ''."\n".
- ' | '."\n".
- ''.&mt('Encryption Key(s)').' | '.
+ ''.
+ ''.&mt('Not in use').' '.
+ $extra.
+ ''.&mt('Encryption Key(s)').' | '.
- ''.
- ''.&mt('Not in use').' '.
- $extra.
- 'Not set yet | To be done | '; + if ($key ne '') { + $datatable .= ''.$lt{'key'}; + if ($switchserver) { + $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']'; + } else { + $datatable .= ':'; + } + $datatable .= ' '.(' 'x2); + } elsif (!$switchserver) { + $datatable .= ''.$lt{'key'}.':'. + ''. + ' '.(' 'x2); + } + if ($switchserver) { + if ($usable ne '') { + $datatable .= ''. + $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).''. + ''.&mt('Change secret?'). + ''. + (' 'x2). + ''.(' 'x2). + ''. + ' - '.$switchmessage.''. + ''; + } elsif ($key eq '') { + $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.''."\n"; + } else { + $datatable .= ''.&mt('Secret required').' - '.$switchmessage.''."\n"; + } + } else { + if ($usable ne '') { + $datatable .= ''. + $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).''. + ''.&mt('Change?'). + ''. + (' 'x2). + ' '. + ''.&mt('New Secret').':'. + ''. + ''; + } else { + $datatable .= + ''.$lt{'secret'}.':'. + ''. + ''; + } + } + $datatable .= ' '. ''.$lt{'requser'}.':'. ' '."\n". ''."\n". @@ -6679,12 +6332,6 @@ sub print_lti { ' '."\n". ''."\n". (' 'x4). - ''.$lt{'key'}. - ': '. - (' 'x2). - ''.$lt{'secret'}.':'. - ''. - ''. ''. ''.<i_options($i,$current,$itemcount,%lt).''; $itemcount ++; @@ -6713,8 +6360,16 @@ sub print_lti { ''.$lt{'version'}.': '."\n". (' 'x2). - ''.$lt{'lifetime'}.': '."\n". - (' 'x2). + ''.$lt{'lifetime'}.': '."\n"; + if ($switchserver) { + $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.''."\n"; + } else { + $datatable .= ''.$lt{'key'}.': '."\n". + (' 'x2). + ''.$lt{'secret'}.':'. + ' '."\n"; + } + $datatable .= ' '. ''.$lt{'requser'}.':'. ' '."\n". ''."\n". @@ -6722,11 +6377,6 @@ sub print_lti { ''.$lt{'crsinc'}.':'. ' '."\n". ''."\n". - (' 'x4). - ''.$lt{'key'}.': '."\n". - (' 'x2). - ''.$lt{'secret'}.':'. - ' '."\n". ''.<i_options('add',undef,$itemcount,%lt). ''."\n". ''."\n"; @@ -7168,12 +6818,16 @@ sub print_coursedefaults { canclone => "People who may clone a course (besides course's owner and coordinators)", mysqltables => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver', ltiauth => 'Student username in LTI launch of deep-linked URL can be accepted without re-authentication', + domexttool => 'External Tools defined in the domain may be used in courses/communities (by type)', + exttool => 'External Tools can be defined and configured in courses/communities (by type)', ); my %staticdefaults = ( anonsurvey_threshold => 10, uploadquota => 500, postsubmit => 60, mysqltables => 172800, + domexttool => 1, + exttool => 0, ); if ($position eq 'top') { %defaultchecked = ( @@ -7291,11 +6945,33 @@ sub print_coursedefaults { my $currusecredits = 0; my $postsubmitclient = 1; my $ltiauth = 0; + my %domexttool; + my %exttool; my @types = ('official','unofficial','community','textbook','placement'); if (ref($settings) eq 'HASH') { if ($settings->{'ltiauth'}) { $ltiauth = 1; } + if (ref($settings->{'domexttool'}) eq 'HASH') { + foreach my $type (@types) { + if ($settings->{'domexttool'}->{$type}) { + $domexttool{$type} = ' checked="checked"'; + } + } + } else { + foreach my $type (@types) { + if ($staticdefaults{'domexttool'}) { + $domexttool{$type} = ' checked="checked"'; + } + } + } + if (ref($settings->{'exttool'}) eq 'HASH') { + foreach my $type (@types) { + if ($settings->{'exttool'}->{$type}) { + $exttool{$type} = ' checked="checked"'; + } + } + } $currdefresponder = $settings->{'anonsurvey_threshold'}; if (ref($settings->{'uploadquota'}) eq 'HASH') { foreach my $type (keys(%{$settings->{'uploadquota'}})) { @@ -7347,6 +7023,9 @@ sub print_coursedefaults { } else { foreach my $type (@types) { $deftimeout{$type} = $staticdefaults{'postsubmit'}; + if ($staticdefaults{'domexttool'}) { + $domexttool{$type} = ' checked="checked"'; + } } } if (!$currdefresponder) { @@ -7450,7 +7129,35 @@ sub print_coursedefaults { &radiobutton_prefs($current,\@toggles,\%defaultchecked, \%choices,$itemcount,undef,undef,'left'); $datatable .= $table; + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ' '.
+ $choices{'domexttool'}.
+ ' | '.
+ ''.
+ ' |
'.
+ $choices{'exttool'}.
+ ' | '.
+ ''.
+ ' |
'.$titles{'notify'}.' | '.
+ '';
+ if ((@instdoms > 1) || (keys(%by_location) > 0)) {
+ my %curr;
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{'notify'} ne '') {
+ map {$curr{$_}=1;} split(/,/,$settings->{'notify'});
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',
+ 'privacy_notify',%curr);
+ if ($numdc > 0) {
+ $datatable .= $table;
+ } else {
+ $datatable .= &mt('There are no active Domain Coordinators');
+ }
+ } else {
+ $datatable .= &mt('Nothing to set here, as there are no other domains');
+ }
+ $datatable .=' | '.
@@ -10511,9 +10244,9 @@ sub user_formats_row {
} elsif ($colsleft == 1) {
$output .= ' | | ';
}
- $output .= ' |
'.&mt('The following errors occurred: ').'