--- loncom/interface/courseprefs.pm 2022/02/16 00:06:04 1.103 +++ loncom/interface/courseprefs.pm 2022/07/08 04:24:24 1.113 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set configuration settings for a course # -# $Id: courseprefs.pm,v 1.103 2022/02/16 00:06:04 raeburn Exp $ +# $Id: courseprefs.pm,v 1.113 2022/07/08 04:24:24 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -601,10 +601,14 @@ sub handler { ); if (($phase eq 'process') && ($parm_permission->{'process'})) { my @allitems = &get_allitems(%prefs); - &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context, - \@prefs_order,\%prefs,\%values, - $cnum,undef,\@allitems, - 'coursepref',$parm_permission); + my $result = &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context, + \@prefs_order,\%prefs,\%values, + $cnum,undef,\@allitems, + 'coursepref',$parm_permission); + if ((ref($result) eq 'HASH') && (keys(%{$result}))) { + $r->rflush(); + &devalidate_remote_courseprefs($cdom,$cnum,$result); + } } elsif (($phase eq 'display') && ($parm_permission->{'display'})) { my $noedit; if (ref($parm_permission) eq 'HASH') { @@ -812,7 +816,7 @@ sub print_config_box { } sub process_changes { - my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_; + my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype,$lastactref) = @_; my (%newvalues,$errors); if (ref($item) eq 'HASH') { if (ref($changes) eq 'HASH') { @@ -981,7 +985,7 @@ sub process_changes { } } elsif ($action eq 'linkprot') { if (ref($values) eq 'HASH') { - $errors = &process_linkprot($cdom,$cnum,$values->{$action},$changes,'course'); + $errors = &process_linkprot($cdom,$cnum,$values->{$action},$changes,'course',$lastactref); } } else { foreach my $entry (@ordered) { @@ -1477,7 +1481,7 @@ sub process_changes { } sub process_linkprot { - my ($cdom,$cnum,$values,$changes,$context) = @_; + my ($cdom,$cnum,$values,$changes,$context,$lastactref) = @_; my ($home,$dest,$ltiauth,$privkey,$privnum,$cipher,$errors,%linkprot); if (ref($values) eq 'HASH') { foreach my $id (keys(%{$values})) { @@ -1501,7 +1505,7 @@ sub process_linkprot { if (grep(/^\Q$home\E$/,@ids)) { if (ref($domdefs{'privhosts'}) eq 'ARRAY') { if (grep(/^\Q$home\E$/,@{$domdefs{'privhosts'}})) { - my %privhash = &Apache::lonnet::restore_dom('lti','private',$cdom,$home,1); + my %privhash = &Apache::lonnet::restore_dom('lti','private',$cdom,$home,1); $privkey = $privhash{'key'}; $privnum = $privhash{'version'}; if (($privnum) && ($privkey ne '')) { @@ -1544,7 +1548,7 @@ sub process_linkprot { if (ref($values) eq 'HASH') { my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_del'); my $maxnum = $env{'form.linkprot_maxnum'}; - for (my $i=0; $i<=$maxnum; $i++) { + for (my $i=0; $i<$maxnum; $i++) { my $itemid = $env{'form.linkprot_id_'.$i}; $itemid =~ s/\D+//g; if ($itemid) { @@ -1589,11 +1593,28 @@ sub process_linkprot { $linkprot{$itemid}{$inner} = $env{$formitem}; } } + my $urlitem = 'form.linkprot_returnurl_'.$idx; + my $urlparamname = 'form.linkprot_urlparam_'.$idx; + if ($env{$urlitem} == 1) { + $env{$urlparamname} =~ s/(`)/'/g; + } elsif (exists($env{$urlparamname})) { + $env{$urlparamname} = ''; + } + unless ($idx eq 'add') { + if ((!$current{'returnurl'} && ($env{$urlparamname} ne '')) || + ($current{'returnurl'} && ($env{$urlparamname} eq ''))) { + $haschanges{$itemid} = 1; + } + } + if ($env{$urlparamname} ne '') { + $linkprot{$itemid}{'returnurl'} = $env{$urlparamname}; + } if ($ltiauth) { my $reqitem = 'form.linkprot_requser_'.$idx; $env{$reqitem} =~ s/(`)/'/g; unless ($idx eq 'add') { - if ($current{'requser'} ne $env{$reqitem}) { + if ((!$current{'requser'} && $env{$reqitem}) || + ($current{'requser'} && !$env{$reqitem})) { $haschanges{$itemid} = 1; } } @@ -1655,6 +1676,7 @@ sub process_linkprot { } } else { $linkprot{$itemid}{'secret'} = $current{'secret'}; + $linkprot{$itemid}{'cipher'} = $current{'cipher'}; } } elsif ($env{$secretitem} ne '') { if ($privnum && $cipher) { @@ -1671,6 +1693,9 @@ sub process_linkprot { foreach my $entry (keys(%haschanges)) { $changes->{$entry} = $linkprot{$entry}; } + if (ref($lastactref) eq 'HASH') { + $lastactref->{'courselti'} = 1; + } } return $errors; } @@ -2204,6 +2229,9 @@ sub store_linkprot { if (exists($oldlinkprot->{$id}{'usable'})) { $changes->{$id}->{'usable'} = 1; } + if (exists($oldlinkprot->{$id}{'cipher'})) { + $changes->{$id}->{'cipher'} = $oldlinkprot->{$id}{'cipher'}; + } } } } @@ -2254,7 +2282,7 @@ sub store_linkprot { my %values = %{$changes->{$id}}; my %desc = &linkprot_names(); my $display; - foreach my $title ('name','lifetime','version','key','secret') { + foreach my $title ('name','lifetime','version','key','secret','returnurl') { if (($title eq 'key') || ($title eq 'secret')) { if (ref($ltienc{$id}) eq 'HASH') { if (exists($ltienc{$id}{$title})) { @@ -2270,6 +2298,10 @@ sub store_linkprot { if ($values{$title} eq 'LTI-1p0') { $display .= $desc{$title}.': 1.1, '; } + } elsif ($title eq 'returnurl') { + if ($values{$title}) { + $display .= &mt('Return URL parameter').': '.$values{$title}.', '; + } } else { $display .= $desc{$title}.': '.$values{$title}.', '; } @@ -2790,7 +2822,7 @@ function toggleLinkProt(form,num,item) { return; } -function toggleLinkProtReqUser(form,item,extra,valon,styleon,num) { +function toggleLinkProtExtra(form,item,extra,valon,styleon,num) { if (document.getElementById('linkprot_'+extra+'_'+num)) { var extraid = document.getElementById('linkprot_'+extra+'_'+num); var itemname = form.elements['linkprot_'+item+'_'+num]; @@ -2814,6 +2846,16 @@ function toggleLinkProtReqUser(form,item } return; } + +function uncheckLinkProtMakeVis(item,num) { + if (document.getElementById('linkprot_'+item+'_'+num)) { + var currtype = document.getElementById('linkprot_'+item+'_'+num).type; + if (currtype.toLowerCase() == 'checkbox') { + document.getElementById('linkprot_'+item+'_'+num).checked = false; + } + } + return; +} ENDSCRIPT } @@ -5622,9 +5664,6 @@ sub menucollections_display { sub print_linkprotection { my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_; - unless (ref($settings) eq 'HASH') { - return; - } my %linkprotection; my $count = 0; @@ -5669,7 +5708,7 @@ sub print_linkprotection { } } - if (ref($settings->{'linkprot'}) eq 'HASH') { + if ((ref($settings) eq 'HASH') && (ref($settings->{'linkprot'}) eq 'HASH')) { if (keys(%{$settings->{'linkprot'}})) { my @current = sort { $a <=> $b } keys(%{$settings->{'linkprot'}}); $next += $current[-1]; @@ -5690,10 +5729,10 @@ sub print_linkprotection { ''. ''; - my ($usersty,$onclickrequser,%checkedrequser); + my ($usersty,$onclickrequser,%checkedrequser,$onclickreturnurl,%checkedreturnurl); if ($ltiauth) { $usersty = 'display:none'; - $onclickrequser = ' onclick="toggleLinkProtReqUser(this.form,'."'requser','optional','1','block','$i'".');"'; + $onclickrequser = ' onclick="toggleLinkProtExtra(this.form,'."'requser','optional','1','block','$i'".');"'; %checkedrequser = ( no => ' checked="checked"', yes => '', @@ -5707,6 +5746,15 @@ sub print_linkprotection { $usersty = 'display:inline-block'; } } + $onclickreturnurl = ' onclick="toggleLinkProtExtra(this.form,'."'returnurl','divurlparam','1','inline-block','$i'".');"'; + %checkedreturnurl = ( + no => ' checked="checked"', + yes => '', + ); + if ($values{'returnurl'} ne '') { + $checkedreturnurl{'yes'} = $checkedreturnurl{'no'}; + $checkedreturnurl{'no'} = ''; + } $datatable .= ''.$desc{'name'}. ': '. @@ -5715,15 +5763,7 @@ sub print_linkprotection { ' '."\n". (' 'x2). ''.$desc{'lifetime'}.':'; - if ($ltiauth) { - $datatable .= (' 'x2).''.$desc{'requser'}.'?'. - ' '. - ''; - } - $datatable .= '

'; + ' value="'.$values{'lifetime'}.'" size="3"'.$disabled.' />

'; if ($values{'key'} ne '') { $datatable .= ''.$desc{'key'}; if ($noedit) { @@ -5755,6 +5795,7 @@ sub print_linkprotection { } else { $datatable .= ''.&mt('Secret required').' - '.$switchmessage.''."\n"; } + $datatable .= ''; } else { if ($values{'usable'} ne '') { $datatable .= '
'. @@ -5766,18 +5807,32 @@ sub print_linkprotection { '  '; } else { $datatable .= ''.$desc{'secret'}.':'. ''. - ''. + ''. ''; } } + $datatable .= '

'. + ''.$desc{'returnurl'}.'?'. + ' '. + ''. + '   '; if ($ltiauth) { - $datatable .= + $datatable .= (' 'x2).''.$desc{'requser'}.'?'. + ' '. + ''. ''. '
'.$lt{'opti'}.''. &linkprot_options($i,$itemcount,$disabled,\%values,\%desc). @@ -5792,42 +5847,55 @@ sub print_linkprotection { $datatable .= ''."\n". ''."\n". ''.&mt('Add').''."\n". - ''; - my ($usersty,$onclickrequser,%checkedrequser); + ''; + my ($usersty,$onclickrequser,%checkedrequser,$onclickreturnurl,%checkedreturnurl); if ($ltiauth) { $usersty = 'display:none'; - $onclickrequser = ' onclick="toggleLinkProtReqUser(this.form,'."'requser','optional','1','block','add'".');"'; + $onclickrequser = ' onclick="toggleLinkProtExtra(this.form,'."'requser','optional','1','block','add'".');"'; %checkedrequser = ( no => ' checked="checked"', yes => '', ); $datatable .= '
'.$lt{'requ'}.''; } + $onclickreturnurl = ' onclick="toggleLinkProtExtra(this.form,'."'returnurl','divurlparam','1','inline-block','add'".');"'; + %checkedreturnurl = ( + no => ' checked="checked"', + yes => '', + ); $datatable .= ''.$desc{'name'}. ': '."\n". (' 'x2). ''.$desc{'version'}.': '."\n". (' 'x2). - ''.$desc{'lifetime'}.': '."\n"; - if ($ltiauth) { - $datatable .= (' 'x2).''.$desc{'requser'}.'?'. - ' '. - ''; - } - $datatable .= '

'; + ''.$desc{'lifetime'}.': '."\n". + '

'; if ($switchserver) { $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.''."\n"; } else { $datatable .= ''.$desc{'key'}.': '."\n". (' 'x2). ''.$desc{'secret'}.':'. - ' '."\n"; + ' '."\n"; } + $datatable .= '

'. + ''.$desc{'returnurl'}.'?'. + ' '. + ''. + '   '; if ($ltiauth) { - $datatable .= '
'. + $datatable .= (' 'x2).''.$desc{'requser'}.'?'. + ' '. + ''. + '
'. '
'.$lt{'opti'}.''. &linkprot_options('add',$itemcount,$disabled,{},\%desc). '
'; @@ -5844,6 +5912,7 @@ sub linkprot_names { 'lifetime' => 'Nonce lifetime (s)', 'name' => 'Launcher Application', 'secret' => 'Secret', + 'returnurl' => 'Launcher return URL', 'requser' => 'Use identity', 'email' => 'Email address', 'sourcedid' => 'User ID', @@ -5899,7 +5968,7 @@ sub linkprot_options { $checked{'auth'} = ' checked="checked"'; } } - my $onclickuser = ' onclick="toggleLinkProtReqUser(this.form,'."'mapuser','userfield','other','inline-block','$num'".');"'; + my $onclickuser = ' onclick="toggleLinkProtExtra(this.form,'."'mapuser','userfield','other','inline-block','$num'".');"'; my $output = '
'. &mt('Source of LON-CAPA username in LTI request').': '; foreach my $option ('sourcedid','email','other') { @@ -6542,6 +6611,30 @@ sub change_clone { } } } + return; +} + +sub devalidate_remote_courseprefs { + my ($cdom,$cnum,$cachekeys) = @_; + return unless (ref($cachekeys) eq 'HASH'); + my %servers = &Apache::lonnet::internet_dom_servers($cdom); + my %thismachine; + map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids(); + my @posscached = ('courselti'); + 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($cdom.'_'.$cnum)); + } + } + if (@cached) { + &Apache::lonnet::remote_devalidate_cache($server,\@cached); + } + } + } return; }