--- loncom/interface/domainprefs.pm 2023/09/04 17:40:47 1.160.6.118.2.15 +++ loncom/interface/domainprefs.pm 2024/02/25 06:15:54 1.160.6.118.2.19 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.160.6.118.2.15 2023/09/04 17:40:47 raeburn Exp $ +# $Id: domainprefs.pm,v 1.160.6.118.2.19 2024/02/25 06:15:54 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -595,6 +595,8 @@ sub handler { col2 => 'Settings'}, {col1 => 'Rules for shared secrets', col2 => 'Settings'}, + {col1 => 'Link Protectors in Courses', + col2 => 'Values'}, {col1 => 'Link Protectors', col2 => 'Settings'}, {col1 => 'Consumers', @@ -936,9 +938,26 @@ sub print_config_box { $colspan = ' colspan="2"'; } elsif ($action eq 'passwords') { $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'lti') { + $output .= $item->{'print'}->('upper',$dom,$settings,\$rowtotal).' + + + + + + + + + + '."\n". + $item->{'print'}->('middle',$dom,$settings,\$rowtotal); } else { $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal); } + my $hdridx = 2; + if ($action eq 'lti') { + $hdridx = 3; + } $output .= '
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
@@ -947,8 +966,8 @@ sub print_config_box { - - + + '."\n"; if ($action eq 'coursecategories') { $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); @@ -958,6 +977,7 @@ sub print_config_box { } else { $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal); } + $hdridx ++; $output .= '
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).''.&mt($item->{'header'}->[$hdridx]->{'col1'}).''.&mt($item->{'header'}->[$hdridx]->{'col2'}).'
@@ -967,8 +987,8 @@ sub print_config_box { - - '."\n"; + + '."\n"; if ($action eq 'passwords') { $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal); } else { @@ -5273,7 +5293,7 @@ sub print_lti { my ($position,$dom,$settings,$rowtotal) = @_; my $itemcount = 1; my ($datatable,$css_class); - my (%rules,%encrypt,%privkeys,%linkprot); + my (%rules,%encrypt,%privkeys,%linkprot,%suggestions); if (ref($settings) eq 'HASH') { if ($position eq 'top') { if (exists($settings->{'encrypt'})) { @@ -5296,12 +5316,18 @@ sub print_lti { } } } - } elsif ($position eq 'middle') { + } elsif ($position eq 'upper') { if (exists($settings->{'rules'})) { if (ref($settings->{'rules'}) eq 'HASH') { %rules = %{$settings->{'rules'}}; } } + } elsif ($position eq 'middle') { + if (exists($settings->{'suggested'})) { + if (ref($settings->{'suggested'}) eq 'HASH') { + %suggestions = %{$settings->{'suggested'}}; + } + } } elsif ($position eq 'lower') { if (exists($settings->{'linkprot'})) { if (ref($settings->{'linkprot'}) eq 'HASH') { @@ -5312,7 +5338,7 @@ sub print_lti { } } } else { - foreach my $key ('encrypt','private','rules','linkprot') { + foreach my $key ('encrypt','private','rules','linkprot','suggestions') { if (exists($settings->{$key})) { delete($settings->{$key}); } @@ -5321,11 +5347,14 @@ sub print_lti { } if ($position eq 'top') { $datatable = &secrets_form($dom,'ltisec',\%encrypt,\%privkeys,$rowtotal); - } elsif ($position eq 'middle') { + } elsif ($position eq 'upper') { $datatable = &password_rules('ltisecrets',\$itemcount,\%rules); $$rowtotal += $itemcount; + } elsif ($position eq 'middle') { + $datatable = &linkprot_suggestions(\%suggestions,\$itemcount); + $$rowtotal += $itemcount; } elsif ($position eq 'lower') { - $datatable .= &Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain'); + $datatable .= &Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain'); } else { my ($switchserver,$switchmessage); $switchserver = &check_switchserver($dom); @@ -5911,7 +5940,57 @@ sub ltimenu_titles { ); } - +sub linkprot_suggestions { + my ($suggested,$itemcount) = @_; + my $count = 0; + my $next = 1; + my %lt = &Apache::lonlocal::texthash( + 'name' => 'Suggested Launcher', + 'info' => 'Recommendations', + ); + my ($datatable,$css_class,$dest); + if (ref($suggested) eq 'HASH') { + my @current = sort { $a <=> $b } keys(%{$suggested}); + $next += $current[-1]; + for (my $i=0; $i<@current; $i++) { + my $num = $current[$i]; + my %values; + if (ref($suggested->{$num}) eq 'HASH') { + %values = %{$suggested->{$num}}; + } else { + next; + } + $css_class = $$itemcount%2?' class="LC_odd_row"':''; + $datatable .= + ''."\n"; + $$itemcount ++; + } + } + $css_class = $$itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''."\n". + ''."\n"; + return $datatable; +} sub print_coursedefaults { my ($position,$dom,$settings,$rowtotal) = @_; @@ -7048,8 +7127,9 @@ sub print_wafproxy { my $dom_in_effect; my $aliasrows = ''. ''; + &mt('Hostname').': '. + ''. + &Apache::lonnet::hostname($server).''; if ($othercontrol{$server}) { $dom_in_effect = $othercontrol{$server}; my ($current,$forsaml); @@ -13172,7 +13252,6 @@ sub lti_security_results { off => &mt('Encryption of stored external tool secrets defined in domain disabled'), }, ); - } my @types= ('crs','dom'); if ($context eq 'lti') { @@ -13268,6 +13347,28 @@ sub lti_security_results { } } elsif ($item eq 'linkprot') { next; + } elsif ($item eq 'suggested') { + if ((ref($secchanges->{'suggested'}) eq 'HASH') && + (ref($newsec->{'suggested'}) eq 'HASH')) { + my $suggestions; + foreach my $id (sort { $a <=> $b } keys(%{$secchanges->{'suggested'}})) { + if (ref($newsec->{'suggested'}->{$id}) eq 'HASH') { + my $name = $newsec->{'suggested'}->{$id}->{'name'}; + my $info = $newsec->{'suggested'}->{$id}->{'info'}; + $suggestions .= '
  • '.&mt('Launcher: [_1]',$name).'
    '. + &mt('Recommend: [_1]','
    '.$info.'
    '). + '
  • '; + } else { + $suggestions .= '
  • '.&mt('Recommendations deleted for Launcher: [_1]', + $newsec->{'suggested'}->{$id}).'
  • '; + } + } + if ($suggestions) { + $output .= '
  • '.&mt('Hints in Courses for Link Protector Configuration'). + ''. + '
  • '; + } + } } } if ($needs_update) { @@ -13339,7 +13440,7 @@ sub modify_lti { } } if (ref($currltisec{'linkprot'}) eq 'HASH') { - foreach my $id (%{$currltisec{'linkprot'}}) { + foreach my $id (keys(%{$currltisec{'linkprot'}})) { next if ($id !~ /^\d+$/); unless (exists($linkprotchg{$id})) { if (ref($currltisec{'linkprot'}{$id}) eq 'HASH') { @@ -13361,17 +13462,75 @@ sub modify_lti { if ($proterror) { $errors .= '
  • '.$proterror.'
  • '; } + + my (%delsuggested,%suggids,@suggested);; + if (ref($currltisec{'suggested'}) eq 'HASH') { + my $maxnum = $env{'form.linkprot_suggested_maxnum'}; + my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_suggested_del'); + for (my $i=0; $i<$maxnum; $i++) { + my $itemid = $env{'form.linkprot_suggested_id_'.$i}; + $itemid =~ s/\D+//g; + if ($itemid) { + if (ref($currltisec{'suggested'}->{$itemid}) eq 'HASH') { + push(@suggested,$i); + $suggids{$i} = $itemid; + if ((@todelete > 0) && (grep(/^$i$/,@todelete))) { + if (ref($currltisec{'suggested'}{$itemid}) eq 'HASH') { + $delsuggested{$itemid} = $currltisec{'suggested'}{$itemid}{'name'}; + } + } else { + if ($env{'form.linkprot_suggested_name_'.$i} eq '') { + $delsuggested{$itemid} = $currltisec{'suggested'}{$itemid}{'name'}; + } else { + $env{'form.linkprot_suggested_name_'.$i} =~ s/(`)/'/g; + $env{'form.linkprot_suggested_info_'.$i} =~ s/(`)/'/g; + $newltisec{'suggested'}{$itemid}{'name'} = $env{'form.linkprot_suggested_name_'.$i}; + $newltisec{'suggested'}{$itemid}{'info'} = $env{'form.linkprot_suggested_info_'.$i}; + if (($currltisec{'suggested'}{$itemid}{'name'} ne $newltisec{'suggested'}{$itemid}{'name'}) || + ($currltisec{'suggested'}{$itemid}{'info'} ne $newltisec{'suggested'}{$itemid}{'info'})) { + $secchanges{'suggested'}{$itemid} = 1; + } + } + } + } + } + } + } + foreach my $key (keys(%delsuggested)) { + $newltisec{'suggested'}{$key} = $delsuggested{$key}; + $secchanges{'suggested'}{$key} = 1; + } + if (($env{'form.linkprot_suggested_add'}) && + ($env{'form.linkprot_suggested_name_add'} ne '')) { + $env{'form.linkprot_suggested_name_add'} =~ s/(`)/'/g; + $env{'form.linkprot_suggested_info_add'} =~ s/(`)/'/g; + my ($newsuggid,$errormsg) = &get_lti_id($dom,$env{'form.linkprot_suggested_name_add'},'suggested'); + if ($newsuggid) { + $newltisec{'suggested'}{$newsuggid}{'name'} = $env{'form.linkprot_suggested_name_add'}; + $newltisec{'suggested'}{$newsuggid}{'info'} = $env{'form.linkprot_suggested_info_add'}; + $secchanges{'suggested'}{$newsuggid} = 1; + } else { + my $error = &mt('Failed to acquire unique ID for new Link Protectors in Courses Suggestion'); + if ($errormsg) { + $error .= ' ('.$errormsg.')'; + } + $errors .= '
  • '.$error.'
  • '; + } + } my (@items,%deletions,%itemids); if ($env{'form.lti_add'}) { my $consumer = $env{'form.lti_consumer_add'}; $consumer =~ s/(`)/'/g; - ($newid,my $error) = &get_lti_id($dom,$consumer); + ($newid,my $errormsg) = &get_lti_id($dom,$consumer,'lti'); if ($newid) { $itemids{'add'} = $newid; push(@items,'add'); $changes{$newid} = 1; } else { my $error = &mt('Failed to acquire unique ID for new LTI configuration'); + if ($errormsg) { + $error .= ' ('.$errormsg.')'; + } $errors .= '
  • '.$error.'
  • '; } } @@ -13965,7 +14124,8 @@ sub modify_lti { } $resulttext .= ''; if (ref($lastactref) eq 'HASH') { - if (($secchanges{'encrypt'}) || ($secchanges{'private'})) { + if (($secchanges{'encrypt'}) || ($secchanges{'private'}) || (exists($secchanges{'suggested'}))) { + &Apache::lonnet::get_domain_defaults($dom,1); $lastactref->{'domdefaults'} = 1; } } @@ -14004,23 +14164,26 @@ sub get_priv_creds { } sub get_lti_id { - my ($domain,$consumer) = @_; - # get lock on lti db + my ($domain,$consumer,$dbname) = @_; + unless (($dbname eq 'lti') || ($dbname eq 'suggested')) { + return ('','invalid db'); + } + # get lock on db my $lockhash = { lock => $env{'user.name'}. ':'.$env{'user.domain'}, }; my $tries = 0; - my $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain); + my $gotlock = &Apache::lonnet::newput_dom($dbname,$lockhash,$domain); my ($id,$error); while (($gotlock ne 'ok') && ($tries<10)) { $tries ++; sleep (0.1); - $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain); + $gotlock = &Apache::lonnet::newput_dom($dbname,$lockhash,$domain); } if ($gotlock eq 'ok') { - my %currids = &Apache::lonnet::dump_dom('lti',$domain); + my %currids = &Apache::lonnet::dump_dom($dbname,$domain); if ($currids{'lock'}) { delete($currids{'lock'}); if (keys(%currids)) { @@ -14032,14 +14195,14 @@ sub get_lti_id { $id = 1; } if ($id) { - unless (&Apache::lonnet::newput_dom('lti',{ $id => $consumer },$domain) eq 'ok') { + unless (&Apache::lonnet::newput_dom($dbname,{ $id => $consumer },$domain) eq 'ok') { $error = 'nostore'; } } else { $error = 'nonumber'; } } - my $dellockoutcome = &Apache::lonnet::del_dom('lti',['lock'],$domain); + my $dellockoutcome = &Apache::lonnet::del_dom($dbname,['lock'],$domain); } else { $error = 'nolock'; }
    '.&mt($item->{'header'}->[3]->{'col1'}).''.&mt($item->{'header'}->[3]->{'col2'}).'
    '.&mt($item->{'header'}->[$hdridx]->{'col1'}).''.&mt($item->{'header'}->[$hdridx]->{'col2'}).'
    '."\n". + ''."\n". + '
    '.$lt{'name'}.''."\n". + ''."\n". + '
    '. + '
    '.$lt{'info'}.''."\n". + ''. + '
    '. + '
    '."\n". + '
    '."\n". + ''."\n". + ''.&mt('Add').''."\n". + '
    '.$lt{'name'}.''."\n". + ''."\n". + '
    '. + '
    '.$lt{'info'}.''."\n". + ''. + '
    '. + '
    '."\n". + '
    '. - &mt('Hostname').': '. - ''.&Apache::lonnet::hostname($server).'