--- loncom/auth/lonauth.pm 2021/12/30 05:11:28 1.121.2.24 +++ loncom/auth/lonauth.pm 2021/12/30 06:00:16 1.121.2.24.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network # User Authentication Module # -# $Id: lonauth.pm,v 1.121.2.24 2021/12/30 05:11:28 raeburn Exp $ +# $Id: lonauth.pm,v 1.121.2.24.2.1 2021/12/30 06:00:16 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -29,7 +29,7 @@ package Apache::lonauth; use strict; -use LONCAPA; +use LONCAPA qw(:DEFAULT :match); use Apache::Constants qw(:common); use CGI qw(:standard); use Apache::loncommon(); @@ -148,6 +148,22 @@ sub success { $destination .= 'source=login'; } + if (($env{'request.deeplink.login'} eq $lowerurl) && + (($env{'request.linkprot'}) || ($env{'request.linkkey'} ne ''))) { + my %info; + if ($env{'request.linkprot'}) { + $info{'linkprot'} = $env{'request.linkprot'}; + } elsif ($env{'request.linkkey'} ne '') { + $info{'linkkey'} = $env{'request.linkkey'}; + } + $info{'origurl'} = $lowerurl; + my $token = &Apache::lonnet::tmpput(\%info,$r->dir_config('lonHostID'),'link'); + unless (($token eq 'con_lost') || ($token eq 'refused') || + ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) { + $destination .= (($destination =~ /\?/) ? '&' : '?') . 'ttoken='.$token; + } + } + my $windowinfo=&Apache::lonmenu::open($env{'browser.os'}); my $startupremote=&Apache::lonmenu::startupremote($destination); my $remoteinfo=&Apache::lonmenu::load_remote_msg($lowerurl); @@ -251,6 +267,20 @@ sub failed { my $firsturl = &Apache::loncommon::cleanup_html($form->{firsturl}); if ($firsturl ne '') { $retry .= (($retry=~/\?/)?'&':'?').'firsturl='.$firsturl; + if ($form->{firsturl} =~ m{^/tiny/$match_domain/\w+$}) { + unless (exists($form->{linkprot})) { + if (exists($form->{linkkey})) { + $retry .= 'linkkey='.$form->{linkkey}; + } + } + } + } + } + if (exists($form->{linkprot})) { + my $ltoken = &Apache::lonnet::tmpput({linkprot => $form->{'linkprot'}}, + $r->dir_config('lonHostID'),'retry'); + if ($ltoken) { + $retry .= (($retry =~ /\?/) ? '&' : '?').'ltoken='.$ltoken; } } } elsif ($querystr ne '') { @@ -333,6 +363,45 @@ sub handler { if ($firsturl ne '') { $info{'firsturl'} = $firsturl; $dest = $firsturl; + my $relogin; + if ($dest =~ m{^/tiny/$match_domain/\w+$}) { + if ($env{'request.course.id'}) { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $symb = &Apache::loncommon::symb_from_tinyurl($dest,$cnum,$cdom); + if ($symb) { + unless (&set_deeplink_login(%info) eq 'ok') { + $relogin = 1; + } + } + } + if ($relogin) { + $r->print( + $start_page + .'

'.&mt('You are already logged in!').'

' + .'

'.&mt('Please [_1]log out[_2] first, and then try your access again', + '','') + .'

' + .$end_page); + } else { + if (($info{'linkprot'}) || ($info{'linkkey'} ne '')) { + my $token = &Apache::lonnet::tmpput(\%info,$r->dir_config('lonHostID'),'link'); + unless (($token eq 'con_lost') || ($token eq 'refused') || + ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) { + $dest .= (($dest =~ /\?/) ? '&' : '?') . 'ttoken='.$token; + } + } + $r->print( + $start_page + .'

'.&mt('You are already logged in!').'

' + .'

'.&mt('Please either [_1]continue the current session[_2] or [_3]log out[_4] first, and then try your access again', + '','', + '','') + .'

' + .$end_page); + } + return OK; + } } } } @@ -400,6 +469,9 @@ sub handler { my ($key,$value) = split(/=/,$item); $form{$key} = &unescape($value); } + if ($firsturl =~ m{^/tiny/$match_domain/\w+$}) { + $form{'firsturl'} = $firsturl; + } my $upass = &Apache::loncommon::des_decrypt($des_key,$form{'upass0'}); # ---------------------------------------------------------------- Authenticate @@ -584,6 +656,14 @@ sub handler { if ($form{'symb'}) { $switchto .= '&symb='.$form{'symb'}; } + if ($form{'linkprot'}) { + $env{'request.linkprot'} = $form{'linkprot'}; + } elsif ($form{'linkkey'} ne '') { + $env{'request.linkkey'} = $form{'linkkey'}; + } + if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { + &set_deeplink_login(%form); + } $r->internal_redirect($switchto); } else { &Apache::loncommon::content_type($r,'text/html'); @@ -607,6 +687,14 @@ sub handler { if ($form{'symb'}) { $switchto .= '&symb='.$form{'symb'}; } + if ($form{'linkprot'}) { + $env{'request.linkprot'} = $form{'linkprot'}; + } elsif ($form{'linkkey'} ne '') { + $env{'request.linkkey'} = $form{'linkkey'}; + } + if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { + &set_deeplink_login(%form); + } $r->internal_redirect($switchto); } else { &Apache::loncommon::content_type($r,'text/html'); @@ -638,6 +726,14 @@ sub handler { if ($unloaded) { &success($r,$form{'uname'},$form{'udom'},$authhost,'noredirect', undef,\%form); + if ($form{'linkprot'}) { + $env{'request.linkprot'} = $form{'linkprot'}; + } elsif ($form{'linkkey'} ne '') { + $env{'request.linkkey'} = $form{'linkkey'}; + } + if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { + &set_deeplink_login(%form); + } $r->internal_redirect('/adm/switchserver?otherserver='.$unloaded.'&origurl='.$firsturl); return OK; } @@ -658,7 +754,40 @@ sub handler { } } } - &success($r,$form{'uname'},$form{'udom'},$authhost,$firsturl,undef, + if ($form{'linkprot'}) { + my ($linkprotector,$uri) = split(/:/,$form{'linkprot'},2); + if ($linkprotector) { + $extra_env = {'user.linkprotector' => $linkprotector, + 'user.linkproturi' => $uri}; + } + } elsif ($form{'linkkey'} ne '') { + $extra_env = {'user.deeplinkkey' => $form{'linkkey'}, + 'user.keyedlinkuri' => $form{'firsturl'}}; + } + if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { + &set_deeplink_login(%form); + if ($form{'linkprot'}) { + if (ref($extra_env) eq 'HASH') { + %{$extra_env} = ( %{$extra_env}, 'request.linkprot' => $form{'linkprot'} ); + } else { + $extra_env = {'request.linkprot' => $form{'linkprot'}}; + } + } elsif ($form{'linkkey'} ne '') { + if (ref($extra_env) eq 'HASH') { + %{$extra_env} = ( %{$extra_env}, 'request.linkkey' => $form{'linkkey'} ); + } else { + $extra_env = {'request.linkkey' => $form{'linkkey'}}; + } + } + if ($env{'request.deeplink.login'}) { + if (ref($extra_env) eq 'HASH') { + %{$extra_env} = ( %{$extra_env}, 'request.deeplink.login' => $form{'firsturl'} ); + } else { + $extra_env = {'request.deeplink.login' => $form{'firsturl'}}; + } + } + } + &success($r,$form{'uname'},$form{'udom'},$authhost,$firsturl,$extra_env, \%form); return OK; } @@ -680,11 +809,58 @@ sub get_form_items { return %form; } +sub set_deeplink_login { + my (%form) = @_; + my $disallow; + if ($form{'firsturl'} =~ m{^/tiny/($match_domain)/\w+$}) { + my $cdom = $1; + my ($cnum,$symb) = &Apache::loncommon::symb_from_tinyurl($form{'firsturl'},'',$cdom); + if ($symb) { + if ($env{'request.course.id'} eq $cdom.'_'.$cnum) { + my $deeplink; + if ($symb =~ /\.(page|sequence)$/) { + my $mapname = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($symb))[2]); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (ref($navmap)) { + $deeplink = $navmap->get_mapparam(undef,$mapname,'0.deeplink'); + } + } else { + $deeplink = &Apache::lonnet::EXT('resource.0.deeplink',$symb); + } + if ($deeplink ne '') { + my ($state,$others,$listed,$scope,$protect) = split(/,/,$deeplink); + if (($protect ne 'none') && ($protect ne '')) { + my ($acctype,$item) = split(/:/,$protect); + if ($acctype =~ /lti(c|d)$/) { + unless ($form{'linkprot'} eq $item.$1.':'.$env{'request.deeplink.login'}) { + $disallow = 1; + } + } elsif ($acctype eq 'key') { + unless ($form{'linkkey'} eq $item) { + $disallow = 1; + } + } + } + } + unless ($disallow) { + $env{'request.deeplink.login'} = $form{'firsturl'}; + } + } else { + $env{'request.deeplink.login'} = $form{'firsturl'}; + } + } + } + if ($disallow) { + return; + } + return 'ok'; +} + sub set_retry_token { my ($form,$lonhost,$querystr) = @_; if (ref($form) eq 'HASH') { my ($firsturl,$token,$extras,@names); - @names = ('role','symb','iptoken'); + @names = ('role','symb','linkprot','linkkey','iptoken'); foreach my $name (@names) { if ($form->{$name} ne '') { $extras .= '&'.$name.'='.&escape($form->{$name}); @@ -752,6 +928,7 @@ sub check_can_host { my $alias = &Apache::lonnet::use_proxy_alias($r,$login_host); $hostname = $alias if ($alias ne ''); my $newurl = $protocol.'://'.$hostname.'/adm/createaccount'; +#FIXME Should preserve where user was going and linkprot by setting ltoken at $login_host $r->print(&Apache::loncommon::start_page('Create a user account in LON-CAPA'). '

'.&mt('Account creation').'

'. &mt('You do not currently have a LON-CAPA account at this institution.').'
'. @@ -768,6 +945,14 @@ sub check_can_host { } else { &success($r,$form->{'uname'},$udom,$authhost,'noredirect',undef, $form); + if ($form->{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { + $env{'request.deeplink.login'} = $form->{'firsturl'}; + } + if ($form->{'linkprot'}) { + $env{'request.linkprot'} = $form->{'linkprot'}; + } elsif ($form->{'linkkey'} ne '') { + $env{'request.linkkey'} = $form->{'linkkey'}; + } my ($otherserver) = &Apache::lonnet::choose_server($udom); $r->internal_redirect('/adm/switchserver?otherserver='.$otherserver); }