[LON-CAPA-cvs] cvs: doc /loncapafiles loncapafiles.lpml loncom loncapa_apache.conf loncron lond loncom/interface domainprefs.pm lonconfigsettings.pm loncom/lonnet/perl lonnet.pm loncom/lti ltiauth.pm ltilogout.pm ltiutils.pm
raeburn
raeburn at source.lon-capa.org
Thu Jul 18 14:29:05 EDT 2019
raeburn Thu Jul 18 18:29:05 2019 EDT
Added files:
/loncom/lti ltilogout.pm
Modified files:
/loncom lond loncron loncapa_apache.conf
/loncom/lti ltiutils.pm ltiauth.pm
/loncom/interface domainprefs.pm lonconfigsettings.pm
/loncom/lonnet/perl lonnet.pm
/doc/loncapafiles loncapafiles.lpml
Log:
- Bug 6754. LON-CAPA as LTI Provider.
Domain configuration to support session expiration in LON-CAPA,
after user logs out of LTI Consumer which originally launched session,
(if Consumer supports logoutServiceUrl; e.g. custom_logout_url in Canvas).
-------------- next part --------------
Index: loncom/lond
diff -u loncom/lond:1.559 loncom/lond:1.560
--- loncom/lond:1.559 Tue Jul 2 19:40:18 2019
+++ loncom/lond Thu Jul 18 18:28:40 2019
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.559 2019/07/02 19:40:18 raeburn Exp $
+# $Id: lond,v 1.560 2019/07/18 18:28:40 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -65,7 +65,7 @@
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.559 $'; #' stupid emacs
+my $VERSION='$Revision: 1.560 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid="default";
my $currentdomainid;
@@ -227,6 +227,7 @@
dcmailput => {remote => 1, domroles => 1},
del => {remote => 1, domroles => 1, enroll => 1, content => 1},
delbalcookie => {institutiononly => 1},
+ delusersession => {institutiononly => 1},
deldom => {remote => 1, domroles => 1}, # not currently used
devalidatecache => {institutiononly => 1},
domroleput => {remote => 1, enroll => 1},
@@ -3033,6 +3034,54 @@
}
®ister_handler("userhassession", \&user_has_session_handler, 0,1,0);
+sub del_usersession_handler {
+ my ($cmd, $tail, $client) = @_;
+
+ my $result;
+ my ($udom, $uname) = map { &unescape($_) } (split(/:/, $tail));
+ if (($udom =~ /^$LONCAPA::match_domain$/) && ($uname =~ /^$LONCAPA::match_username$/)) {
+ my $lonidsdir = $perlvar{'lonIDsDir'};
+ if (-d $lonidsdir) {
+ if (opendir(DIR,$lonidsdir)) {
+ my $filename;
+ while ($filename=readdir(DIR)) {
+ if ($filename=~/^\Q$uname\E_\d+_\Q$udom\E_/) {
+ if (tie(my %oldenv,'GDBM_File',"$lonidsdir/$filename",
+ &GDBM_READER(),0640)) {
+ my $linkedfile;
+ if (exists($oldenv{'user.linkedenv'})) {
+ $linkedfile = $oldenv{'user.linkedenv'};
+ }
+ untie(%oldenv);
+ $result = unlink("$lonidsdir/$filename");
+ if ($result) {
+ if ($linkedfile =~ /^[a-f0-9]+_linked$/) {
+ if (-l "$lonidsdir/$linkedfile.id") {
+ unlink("$lonidsdir/$linkedfile.id");
+ }
+ }
+ }
+ } else {
+ $result = unlink("$lonidsdir/$filename");
+ }
+ last;
+ }
+ }
+ }
+ }
+ if ($result == 1) {
+ &Reply($client, "$result\n", "$cmd:$tail");
+ } else {
+ &Reply($client, "not_found\n", "$cmd:$tail");
+ }
+ } else {
+ &Failure($client, "invalid_user\n", "$cmd:$tail");
+ }
+ return 1;
+}
+
+®ister_handler("delusersession", \&del_usersession_handler, 0,1,0);
+
#
# Authenticate access to a user file by checking that the token the user's
# passed also exists in their session file
Index: loncom/loncron
diff -u loncom/loncron:1.118 loncom/loncron:1.119
--- loncom/loncron:1.118 Mon Mar 18 00:37:37 2019
+++ loncom/loncron Thu Jul 18 18:28:40 2019
@@ -2,7 +2,7 @@
# Housekeeping program, started by cron, loncontrol and loncron.pl
#
-# $Id: loncron,v 1.118 2019/03/18 00:37:37 raeburn Exp $
+# $Id: loncron,v 1.119 2019/07/18 18:28:40 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -567,6 +567,34 @@
}
}
+# ------------------------------------------------------------ clean out ltiIDs
+
+sub clean_ltiIDs {
+ my ($fh)=@_;
+ &log($fh,'<hr /><a name="ltisessions" /><h2>LTI Session Pointers</h2>');
+ my $cleaned=0;
+ my $active=0;
+ if (-d $perlvar{'ltiIDsDir'}) {
+ while (my $fname=<$perlvar{'ltiIDsDir'}/*>) {
+ my ($dev,$ino,$mode,$nlink,
+ $uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,
+ $blksize,$blocks)=stat($fname);
+ my $now=time;
+ my $since=$now-$mtime;
+ if ($since>$perlvar{'lonExpire'}) {
+ $cleaned++;
+ &log($fh,"Unlinking $fname<br />");
+ unlink("$fname");
+ } else {
+ $active++;
+ }
+ }
+ }
+ &log($fh,"<p>Cleaned up ".$cleaned." old LTI session pointers.</p>");
+ &log($fh,"<h3>$active unexpired LTI session pointers</h3>");
+}
+
# ----------------------------------------------------------- clean out sockets
sub clean_sockets {
my ($fh)=@_;
@@ -1595,6 +1623,7 @@
&clean_lonIDs($fh);
&clean_balanceIDs($fh);
&clean_webDAV_sessionIDs($fh);
+ &clean_ltiIDs($fh);
&check_httpd_logs($fh);
&rotate_lonnet_logs($fh);
&rotate_other_logs($fh);
Index: loncom/loncapa_apache.conf
diff -u loncom/loncapa_apache.conf:1.268 loncom/loncapa_apache.conf:1.269
--- loncom/loncapa_apache.conf:1.268 Thu May 2 02:18:10 2019
+++ loncom/loncapa_apache.conf Thu Jul 18 18:28:40 2019
@@ -2,7 +2,7 @@
## loncapa_apache.conf -- Apache HTTP LON-CAPA configuration file
##
-# $Id: loncapa_apache.conf,v 1.268 2019/05/02 02:18:10 raeburn Exp $
+# $Id: loncapa_apache.conf,v 1.269 2019/07/18 18:28:40 raeburn Exp $
#
# LON-CAPA Section (extensions to httpd.conf daemon configuration)
@@ -780,6 +780,11 @@
PerlHandler Apache::ltiroster
</Location>
+<LocationMatch "^/adm/service/logout/\w+$">
+SetHandler perl-script
+PerlHandler Apache::ltilogout
+</LocationMatch>
+
<Location /adm/restrictedaccess>
PerlAccessHandler Apache::publiccheck
AuthType LONCAPA
@@ -1784,6 +1789,7 @@
PerlSetVar lonCaptchaDir /home/httpd/captchaspool
PerlSetVar lonCaptchaDb /home/httpd/captchadb
PerlSetVar lonLTIDir /home/httpd/lonLTItmp
+PerlSetVar ltiIDsDir /home/httpd/ltiIDs
PerlSetVar lonFontsDir /home/httpd/html/adm/fonts
# & separated list of % separated fields in order of
# - internal name to call it,
Index: loncom/lti/ltiutils.pm
diff -u loncom/lti/ltiutils.pm:1.16 loncom/lti/ltiutils.pm:1.17
--- loncom/lti/ltiutils.pm:1.16 Sun Mar 31 18:48:33 2019
+++ loncom/lti/ltiutils.pm Thu Jul 18 18:28:46 2019
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Utility functions for managing LON-CAPA LTI interactions
#
-# $Id: ltiutils.pm,v 1.16 2019/03/31 18:48:33 raeburn Exp $
+# $Id: ltiutils.pm,v 1.17 2019/07/18 18:28:46 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -31,6 +31,7 @@
use strict;
use Net::OAuth;
use Digest::SHA;
+use Digest::MD5 qw(md5_hex);
use UUID::Tiny ':std';
use Apache::lonnet;
use Apache::loncommon;
@@ -339,14 +340,20 @@
#
sub sign_params {
- my ($url,$key,$secret,$sigmethod,$paramsref) = @_;
+ my ($url,$key,$secret,$paramsref,$sigmethod,$type,$callback,$post) = @_;
return unless (ref($paramsref) eq 'HASH');
if ($sigmethod eq '') {
$sigmethod = 'HMAC-SHA1';
}
+ if ($type eq '') {
+ $type = 'request token';
+ }
+ if ($callback eq '') {
+ $callback = 'about:blank',
+ }
srand( time() ^ ($$ + ($$ << 15)) ); # Seed rand.
my $nonce = Digest::SHA::sha1_hex(sprintf("%06x%06x",rand(0xfffff0),rand(0xfffff0)));
- my $request = Net::OAuth->request("request token")->new(
+ my $request = Net::OAuth->request($type)->new(
consumer_key => $key,
consumer_secret => $secret,
request_url => $url,
@@ -354,12 +361,16 @@
signature_method => $sigmethod,
timestamp => time,
nonce => $nonce,
- callback => 'about:blank',
+ callback => $callback,
extra_params => $paramsref,
version => '1.0',
);
$request->sign();
- return $request->to_hash();
+ if ($post) {
+ return $request->to_post_body();
+ } else {
+ return $request->to_hash();
+ }
}
#
@@ -647,7 +658,7 @@
lti_message_type => 'basic-lis-readmembershipsforcontext',
ext_ims_lis_memberships_id => $id,
);
- my $hashref = &sign_params($url,$ckey,$secret,'',\%ltiparams);
+ my $hashref = &sign_params($url,$ckey,$secret,\%ltiparams);
if (ref($hashref) eq 'HASH') {
my $request=new HTTP::Request('POST',$url);
$request->content(join('&',map {
@@ -735,7 +746,7 @@
result_statusofresult => 'final',
result_date => $date,
);
- my $hashref = &sign_params($url,$ckey,$secret,$sigmethod,\%ltiparams);
+ my $hashref = &sign_params($url,$ckey,$secret,\%ltiparams,$sigmethod);
if (ref($hashref) eq 'HASH') {
$request=new HTTP::Request('POST',$url);
$request->content(join('&',map {
@@ -807,6 +818,28 @@
#FIXME Handle case where pass back of score to LTI Consumer failed.
}
+sub setup_logout_callback {
+ my ($uname,$udom,$server,$ckey,$secret,$service_url,$idsdir,$protocol,$hostname) = @_;
+ if ($service_url =~ m{^https?://[^/]+/}) {
+ my $digest_user = &Encode::decode_utf8($uname.':'.$udom);
+ my $loginfile = &Digest::SHA::sha1_hex($digest_user).&md5_hex(&md5_hex(time.{}.rand().$$));
+ if ((-d $idsdir) && (open(my $fh,'>',"$idsdir/$loginfile"))) {
+ print $fh "$uname,$udom,$server\n";
+ close($fh);
+ my $callback = 'http://'.$hostname.'/adm/service/logout/'.$loginfile;
+ my %ltiparams = (
+ callback => $callback,
+ );
+ my $post = &sign_params($service_url,$ckey,$secret,\%ltiparams,
+ '','','',1);
+ my $request=new HTTP::Request('POST',$service_url);
+ $request->content($post);
+ my $response = &LONCAPA::LWPReq::makerequest('',$request,'','',10);
+ }
+ }
+ return;
+}
+
#
# LON-CAPA as LTI Provider
#
Index: loncom/lti/ltiauth.pm
diff -u loncom/lti/ltiauth.pm:1.18 loncom/lti/ltiauth.pm:1.19
--- loncom/lti/ltiauth.pm:1.18 Thu Jun 13 17:45:26 2019
+++ loncom/lti/ltiauth.pm Thu Jul 18 18:28:46 2019
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Basic LTI Authentication Module
#
-# $Id: ltiauth.pm,v 1.18 2019/06/13 17:45:26 raeburn Exp $
+# $Id: ltiauth.pm,v 1.19 2019/07/18 18:28:46 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -749,9 +749,21 @@
}
}
}
+ my $protocol = 'http';
+ if ($ENV{'SERVER_PORT'} == 443) {
+ $protocol = 'https';
+ }
if (($is_balancer) && (!$hosthere)) {
# login but immediately go to switch server.
&Apache::lonauth::success($r,$uname,$udom,$uhome,'noredirect');
+ if (($ltihash->{'callback'}) && ($params->{$ltihash->{'callback'}})) {
+ &LONCAPA::ltiutils::setup_logout_callback($uname,$udom,$otherserver,
+ $ltihash->{'key'},
+ $ltihash->{'secret'},
+ $params->{$ltihash->{'callback'}},
+ $r->dir_config('ltiIDsDir'),
+ $protocol,$r->hostname);
+ }
if ($symb) {
$env{'form.symb'} = $symb;
$env{'request.lti.uri'} = $tail;
@@ -818,6 +830,14 @@
foreach my $key (%{$params}) {
delete($env{'form.'.$key});
}
+ if (($ltihash->{'callback'}) && ($params->{$ltihash->{'callback'}})) {
+ &LONCAPA::ltiutils::setup_logout_callback($uname,$udom,$lonhost,
+ $ltihash->{'key'},
+ $ltihash->{'secret'},
+ $params->{$ltihash->{'callback'}},
+ $r->dir_config('ltiIDsDir'),
+ $protocol,$r->hostname);
+ }
my $ip = $r->get_remote_host();
my %info=('ip' => $ip,
'domain' => $udom,
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.362 loncom/interface/domainprefs.pm:1.363
--- loncom/interface/domainprefs.pm:1.362 Tue Jun 4 03:16:19 2019
+++ loncom/interface/domainprefs.pm Thu Jul 18 18:28:52 2019
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.362 2019/06/04 03:16:19 raeburn Exp $
+# $Id: domainprefs.pm,v 1.363 2019/07/18 18:28:52 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2905,7 +2905,7 @@
}
}
}
- } else if ((setting == 'user') || (setting == 'crs') || (setting == 'passback')) {
+ } else if ((setting == 'user') || (setting == 'crs') || (setting == 'passback') || (setting == 'callback')) {
var radioname = '';
var divid = '';
if (setting == 'user') {
@@ -2914,6 +2914,9 @@
} else if (setting == 'crs') {
radioname = 'lti_mapcrs_'+item;
divid = 'lti_crsfield_'+item;
+ } else if (setting == 'callback') {
+ radioname = 'lti_callback_'+item;
+ divid = 'lti_callbackfield_'+item;
} else {
radioname = 'lti_passback_'+item;
divid = 'lti_passback_'+item;
@@ -2923,7 +2926,7 @@
var setvis = '';
for (var i=0; i<num; i++) {
if (form.elements[radioname][i].checked) {
- if (setting == 'passback') {
+ if ((setting == 'passback') || (setting == 'callback')) {
if (form.elements[radioname][i].value == '1') {
if (document.getElementById(divid)) {
document.getElementById(divid).style.display = 'inline-block';
@@ -4957,7 +4960,7 @@
sub lti_options {
my ($num,$current,$itemcount,%lt) = @_;
- my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield);
+ my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield,$callback);
$checked{'mapuser'}{'sourcedid'} = ' checked="checked"';
$checked{'mapcrs'}{'course_offering_sourcedid'} = ' checked="checked"';
$checked{'makecrs'}{'N'} = ' checked="checked"';
@@ -4975,6 +4978,7 @@
my $crsfieldsty = 'none';
my $crssecfieldsty = 'none';
my $secsrcfieldsty = 'none';
+ my $callbacksty = 'none';
my $passbacksty = 'none';
my $optionsty = 'block';
my $lcauthparm;
@@ -5054,6 +5058,13 @@
} else {
$checked{'crssec'}{'N'} = ' checked="checked"';
}
+ if ($current->{'callback'} ne '') {
+ $callback = $current->{'callback'};
+ $checked{'callback'}{'Y'} = ' checked="checked"';
+ $callbacksty = 'inline-block';
+ } else {
+ $checked{'callback'}{'N'} = ' checked="checked"';
+ }
if ($current->{'topmenu'}) {
$checked{'topmenu'}{'Y'} = ' checked="checked"';
} else {
@@ -5079,6 +5090,7 @@
} else {
$checked{'makecrs'}{'N'} = ' checked="checked"';
$checked{'crssec'}{'N'} = ' checked="checked"';
+ $checked{'callback'}{'N'} = ' checked="checked"';
$checked{'topmenu'}{'N'} = ' checked="checked"';
$checked{'inlinemenu'}{'Y'} = ' checked="checked"';
$checked{'menuitem'}{'grades'} = ' checked="checked"';
@@ -5107,6 +5119,7 @@
my $onclickuser = ' onclick="toggleLTI(this.form,'."'user','$num'".');"';
my $onclickcrs = ' onclick="toggleLTI(this.form,'."'crs','$num'".');"';
my $onclicksec = ' onclick="toggleLTI(this.form,'."'sec','$num'".');"';
+ my $onclickcallback = ' onclick="toggleLTI(this.form,'."'callback','$num'".');"';
my $onclicksecsrc = ' onclick="toggleLTI(this.form,'."'secsrc','$num'".')"';
my $onclicklcauth = ' onclick="toggleLTI(this.form,'."'lcauth','$num'".')"';
my $onclickmenu = ' onclick="toggleLTI(this.form,'."'lcmenu','$num'".');"';
@@ -5256,7 +5269,17 @@
'<label><input type="radio" name="lti_passbackformat_'.$num.'" value="1.1"'.$pb1p1chk.' />'.
&mt('Outcomes Service (1.1)').'</label>'.(' 'x2).
'<label><input type="radio" name="lti_passbackformat_'.$num.'" value="1.0"'.$pb1p0chk.'/>'.
- &mt('Outcomes Extension (1.0)').'</label></span></div></fieldset>'.
+ &mt('Outcomes Extension (1.0)').'</label></span></div>'.
+ '<div style="padding:0;clear:both;margin:0;border:0"></div>'.
+ '<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('Callback on logout').': '.
+ '<label><input type="radio" name="lti_callback_'.$num.'" value="0"'.
+ $checked{'callback'}{'N'}.$onclickcallback.' />'.&mt('No').'</label>'.(' 'x2).
+ '<label><input type="radio" name="lti_callback_'.$num.'" value="1"'.
+ $checked{'callback'}{'Y'}.$onclickcallback.' />'.&mt('Yes').'</label></span></div>'.
+ '<div class="LC_floatleft" style="display:'.$callbacksty.';" id="lti_callbackfield_'.$num.'">'.
+ '<span class="LC_nobreak">'.&mt('Parameter').': '.
+ '<input type="text" name="lti_callbackparam_'.$num.'" value="'.$callback.'" /></span>'.
+ '</div><div style="padding:0;clear:both;margin:0;border:0"></div></fieldset>'.
'<fieldset class="ltioption_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Course defaults (Course Coordinator can override)').'</legend>'.
'<div class="LC_floatleft"><span class="LC_nobreak">'.$lt{'topmenu'}.': '.
'<label><input type="radio" name="lti_topmenu_'.$num.'" value="0"'.
@@ -12675,6 +12698,13 @@
}
}
}
+ 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;
@@ -12700,7 +12730,7 @@
}
}
unless (($idx eq 'add') || ($changes{$itemid})) {
- foreach my $field ('mapuser','mapcrs','makecrs','section','passback','roster','lcauth','lcauthparm','topmenu','inlinemenu') {
+ 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;
}
@@ -12926,6 +12956,11 @@
} else {
$resulttext .= '<li>'.&mt('No section assignment').'</li>';
}
+ if ($confhash{$itemid}{'callback'}) {
+ $resulttext .= '<li>'.&mt('Callback setting').': '.$confhash{$itemid}{'callback'}.'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('No callback to logout LON-CAPA session when user logs out of Comsumer');
+ }
foreach my $item ('passback','roster','topmenu','inlinemenu') {
$resulttext .= '<li>'.$lt{$item}.': ';
if ($confhash{$itemid}{$item}) {
Index: loncom/interface/lonconfigsettings.pm
diff -u loncom/interface/lonconfigsettings.pm:1.45 loncom/interface/lonconfigsettings.pm:1.46
--- loncom/interface/lonconfigsettings.pm:1.45 Sun Jan 27 14:39:48 2019
+++ loncom/interface/lonconfigsettings.pm Thu Jul 18 18:28:52 2019
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: lonconfigsettings.pm,v 1.45 2019/01/27 14:39:48 raeburn Exp $
+# $Id: lonconfigsettings.pm,v 1.46 2019/07/18 18:28:52 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -221,7 +221,8 @@
"toggleLTI(document.display,'sec','add');".
"toggleLTI(document.display,'lcauth','add');".
"toggleLTI(document.display,'lcmenu','add');".
- "toggleLTI(document.display,'passback','add');";
+ "toggleLTI(document.display,'passback','add');".
+ "toggleLTI(document.display,'callback','add');";
if (ref($values) eq 'HASH') {
if (ref($values->{'lti'}) eq 'HASH') {
my $numlti = scalar(keys(%{$values->{'lti'}}));
@@ -231,7 +232,8 @@
"toggleLTI(document.display,'sec','$i');".
"toggleLTI(document.display,'lcauth','$i');".
"toggleLTI(document.display,'lcmenu','$i');".
- "toggleLTI(document.display,'passback','$i');";
+ "toggleLTI(document.display,'passback','$i');".
+ "toggleLTI(document.display,'callback','$i');";
}
}
}
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1410 loncom/lonnet/perl/lonnet.pm:1.1411
--- loncom/lonnet/perl/lonnet.pm:1.1410 Mon May 6 19:28:24 2019
+++ loncom/lonnet/perl/lonnet.pm Thu Jul 18 18:28:58 2019
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1410 2019/05/06 19:28:24 raeburn Exp $
+# $Id: lonnet.pm,v 1.1411 2019/07/18 18:28:58 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1082,6 +1082,19 @@
return;
}
+sub delusersession {
+ my ($lonid,$udom,$uname) = @_;
+ my $uprimary_id = &domain($udom,'primary');
+ my $uintdom = &internet_dom($uprimary_id);
+ my $intdom = &internet_dom($lonid);
+ my $serverhomedom = &host_domain($lonid);
+ if (($uintdom ne '') && ($uintdom eq $intdom)) {
+ return &reply(join(':','delusersession',
+ map {&escape($_)} ($udom,$uname)),$lonid);
+ }
+ return;
+}
+
# check if user's browser sent load balancer cookie and server still has session
# and is not overloaded.
sub check_for_balancer_cookie {
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.990 doc/loncapafiles/loncapafiles.lpml:1.991
--- doc/loncapafiles/loncapafiles.lpml:1.990 Sat Jul 6 19:20:31 2019
+++ doc/loncapafiles/loncapafiles.lpml Thu Jul 18 18:29:04 2019
@@ -2,7 +2,7 @@
"http://lpml.sourceforge.net/DTD/lpml.dtd">
<!-- loncapafiles.lpml -->
-<!-- $Id: loncapafiles.lpml,v 1.990 2019/07/06 19:20:31 raeburn Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.991 2019/07/18 18:29:04 raeburn Exp $ -->
<!--
@@ -503,6 +503,12 @@
<description>cookie jar</description>
</directory>
<directory dist='default'>
+ <protectionlevel>modest_delete</protectionlevel>
+ <targetdir dist='default'>home/httpd/ltiIDs</targetdir>
+ <categoryname>server standard</categoryname>
+ <description>stores LTI callback IDs for session logout</description>
+</directory>
+<directory dist='default'>
<protectionlevel>modest_delete</protectionlevel>
<targetdir dist='default'>home/httpd/balanceIDs</targetdir>
<categoryname>server standard</categoryname>
@@ -2636,6 +2642,16 @@
<status>works/unverified</status>
</file>
<file>
+<source>loncom/lti/ltilogout.pm</source>
+<target dist='default'>home/httpd/lib/perl/Apache/ltilogout.pm</target>
+<categoryname>handler</categoryname>
+<description>
+Handler to logout a LON-CAPA user session on callback from an LTI Consumer
+which launched the session, when user logs out of session on Consumer.
+</description>
+<status>works/unverified</status>
+</file>
+<file>
<source>loncom/lti/ltiutils.pm</source>
<target dist='default'>home/httpd/lib/perl/LONCAPA/ltiutils.pm</target>
<categoryname>system file</categoryname>
Index: loncom/lti/ltilogout.pm
+++ loncom/lti/ltilogout.pm
# The LearningOnline Network with CAPA
# LTI Provider Module to respond to a user session logout request.
#
# $Id: ltilogout.pm,v 1.1 2019/07/18 18:28:46 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
package Apache::ltilogout;
use strict;
use Apache::Constants qw(:common :http);
use Apache::lonnet;
use Apache::loncommon;
sub handler {
my $r = shift;
my ($id) = ($r->uri =~ m{^/adm/service/logout/(\w+)$});
if ($id) {
my $dir = $r->dir_config('ltiIDsDir');
my $lonhost = $r->dir_config('lonHostID');
if (($dir ne '') && (-d $dir)) {
if (-e "$dir/$id") {
if (open(my $fh,'<',"$dir/$id")) {
my $contents = <$fh>;
chomp($contents);
close($fh);
my ($uname,$udom,$hostid) = split(/,/,$contents);
if (($uname ne '') && ($udom ne '')) {
my $uhome = &Apache::lonnet::homeserver($uname,$udom);
if ($uhome ne 'no_host') {
my $lonhost = $r->dir_config('lonHostID');
if ($hostid eq $lonhost) {
&delete_session($udom,$uname);
} else {
my ($is_balancer,$posshost,$setcookie) =
&Apache::lonnet::check_loadbalancing($uname,$udom,'login');
if ($is_balancer) {
if ($setcookie) {
my $balancedir=$r->dir_config('lonBalanceDir');
if (opendir(my $dirh,$balancedir)) {
while (my $filename=readdir($dirh)) {
if ($filename =~/^\Q$udom\E_\Q$uname\E_/) {
if (open(my $fh,'<',"$balancedir/$filename")) {
my $lonid = <$fh>;
close($fh);
if ($lonid eq $lonhost) {
&delete_session($r,$udom,$uname);
} elsif (&Apache::lonnet::hostname($lonid) ne '') {
&Apache::lonnet::delusersession($lonid,$udom,$uname);
}
}
last;
}
}
closedir($dirh);
}
} else {
my $lonid = &Apache::lonnet::find_existing_session($udom,$uname);
if ($lonid eq $lonhost) {
&delete_session($r,$udom,$uname);
} elsif (&Apache::lonnet::hostname($lonid) ne '') {
&Apache::lonnet::delusersession($lonid,$udom,$uname);
}
}
} else {
&delete_session($r,$udom,$uname);
}
}
}
}
}
}
}
}
return OK;
}
sub delete_session {
my ($r,$udom,$uname) = @_;
my $lonidsdir = $r->dir_config('lonIDsDir');
if (-d $lonidsdir) {
if (opendir(my $dir,$lonidsdir)) {
while (my $filename=readdir($dir)) {
if ($filename=~/^\Q$uname\E_\d+_\Q$udom\E_/) {
unlink("$dir/$filename");
last;
}
}
}
}
}
1;
More information about the LON-CAPA-cvs
mailing list