--- loncom/auth/lonroles.pm 2017/05/19 19:20:42 1.330 +++ loncom/auth/lonroles.pm 2020/12/18 15:23:03 1.344 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # User Roles Screen # -# $Id: lonroles.pm,v 1.330 2017/05/19 19:20:42 raeburn Exp $ +# $Id: lonroles.pm,v 1.344 2020/12/18 15:23:03 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -145,6 +145,8 @@ use GDBM_File; use LONCAPA qw(:DEFAULT :match); use HTML::Entities; +my $registered_cleanup; +my $rosterupdates; sub redirect_user { my ($r,$title,$url,$msg) = @_; @@ -153,20 +155,26 @@ sub redirect_user { &Apache::loncommon::no_cache($r); $r->send_http_header; - # Breadcrumbs - my $brcrum = [{'href' => $url, - 'text' => 'Switching Role'},]; - my $start_page = &Apache::loncommon::start_page('Switching Role',undef, - {'redirect' => [1,$url], - 'bread_crumbs' => $brcrum,}); - my $end_page = &Apache::loncommon::end_page(); + my $start_page; + if ($env{'request.lti.login'}) { + $start_page = &Apache::loncommon::start_page(undef,undef, + {'redirect' => [0,$url],}).$msg; + } else { + # Breadcrumbs + my $brcrum = [{'href' => $url, + 'text' => 'Switching Role'},]; + $start_page = &Apache::loncommon::start_page('Switching Role',undef, + {'redirect' => [1,$url], + 'bread_crumbs' => $brcrum,}). + "\n

$msg

"; + } + my $end_page = &Apache::loncommon::end_page(); # Note to style police: # This must only replace the spaces, nothing else, or it bombs elsewhere. $url=~s/ /\%20/g; $r->print(<$msg

$end_page ENDREDIR return; @@ -204,7 +212,7 @@ sub handler { my $r = shift; # Check for critical messages and redirect if present. - my ($redirect,$url) = &Apache::loncommon::critical_redirect(300); + my ($redirect,$url) = &Apache::loncommon::critical_redirect(300,'roles'); if ($redirect) { &Apache::loncommon::content_type($r,'text/html'); $r->header_out(Location => $url); @@ -222,6 +230,8 @@ sub handler { $update = $then; } + $registered_cleanup=0; + @{$rosterupdates}=(); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); # -------------------------------------------------- Check if setting hot list @@ -262,6 +272,12 @@ sub handler { # ================================================================== Roles Init if ($env{'form.selectrole'}) { + if (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq '')) { + if ($env{'form.ltitarget'} eq 'iframe') { + &Apache::lonnet::appenv({'request.lti.target' => 'iframe'}); + delete($env{'form.ltitarget'}); + } + } my $locknum=&Apache::lonnet::get_locks(); if ($locknum) { return 409; } @@ -489,6 +505,7 @@ sub handler { my $end_page=&Apache::loncommon::end_page(); my $buttontext=&mt('Enter Course'); my $message=&mt('Successfully registered key'); + my $ip = &Apache::lonnet::get_requestor_ip(); my $assignresult= &Apache::lonnet::assign_access_key( $env{'form.newkey'}, @@ -497,7 +514,7 @@ sub handler { $env{'user.domain'}, $env{'user.name'}, &mt('Assigned from [_1] at [_2] for [_3]' - ,$ENV{'REMOTE_ADDR'} + ,$ip ,&Apache::lonlocal::locallocaltime() ,$trolecode) ); @@ -578,12 +595,32 @@ ENDENTERKEY my ($furl,$ferr)= &Apache::lonuserstate::readmap($cdom.'/'.$cnum); unless ($ferr) { + &Apache::lonnet::appenv({'request.course.timechecked'=>$now}); unless (($env{'form.switchrole'}) || ($env{"environment.internal.$cdom.$cnum.$role.adhoc"})) { &Apache::lonnet::put('nohist_crslastlogin', {$env{'user.name'}.':'.$env{'user.domain'}. ':'.$csec.':'.$role => $now},$cdom,$cnum); } + if (($env{"environment.internal.$cdom.$cnum.$role.adhoc"}) && + (&Apache::lonnet::allowed('vxc',$cdom.'_'.$cnum))) { + my $owner = $env{'course.'.$cdom.'_'.$cnum.'.internal.courseowner'}; + my @coowners = split(/,/,$env{'course.'.$env{'request.course.id'}.'.internal.co-owners'}); + my %auaccess; + foreach my $user ($owner,@coowners) { + my ($cpname,$cpdom) = split(/:/,$user); + my %auroles = &Apache::lonnet::get_my_roles($cpname,$cpdom,'userroles',undef,['au','ca','aa'],[$cdom]); + foreach my $key (keys(%auroles)) { + my ($auname,$audom,$aurole) = split(/:/,$key); + if ($aurole eq 'au') { + $auaccess{$cpname} = 1; + } else { + $auaccess{$auname} = 1; + } + } + } + &Apache::lonnet::appenv({'request.course.adhocsrcaccess' => join(',',sort(keys(%auaccess))) }); + } my ($feeds,$syllabus_time); &Apache::lonrss::advertisefeeds($cnum,$cdom,undef,\$feeds); &Apache::lonnet::appenv({'request.course.feeds' => $feeds}); @@ -623,6 +660,10 @@ ENDENTERKEY $cdom.'_'.$cnum); } } + if (($env{'request.lti.login'}) && + ($env{'request.lti.rosterid'} || $env{'request.lti.passbackid'})) { + &process_lti($r,$cdom,$cnum); + } $r->internal_redirect($dest); } return OK; @@ -644,6 +685,10 @@ ENDENTERKEY if (($ferr) && ($tadv)) { &error_page($r,$ferr,$furl); } else { + if (($env{'request.lti.login'}) && + ($env{'request.lti.rosterid'} || $env{'request.lti.passbackid'})) { + &process_lti($r,$cdom,$cnum); + } # Check to see if the user is a CC entering a course # for the first time if ((($role eq 'cc') || ($role eq 'co')) @@ -677,9 +722,11 @@ ENDENTERKEY if (($dest =~ m{^\Q/public/$cdom/$cnum/syllabus\E.*(\?|\&)usehttp=1}) || ($dest =~ m{^\Q/adm/wrapper/ext/\E(?!https:)})) { if ($ENV{'SERVER_PORT'} == 443) { - my $hostname = $r->hostname(); - if ($hostname ne '') { - $dest = 'http://'.$hostname.$dest; + unless (&Apache::lonnet::uses_sts()) { + my $hostname = $r->hostname(); + if ($hostname ne '') { + $dest = 'http://'.$hostname.$dest; + } } } } @@ -718,9 +765,12 @@ ENDENTERKEY $dest .= (($dest =~/\?/)? '&':'?').'symb='.$esc_symb; } } - &redirect_user($r, &mt('Entering [_1]', - $env{'course.'.$cdom.'_'.$cnum.'.description'}), - $dest, $msg); + my $title; + unless ($env{'request.lti.login'}) { + $title = &mt('Entering [_1]', + $env{'course.'.$cdom.'_'.$cnum.'.description'}); + } + &redirect_user($r,$title,$dest,$msg); return OK; } if (&Apache::lonnet::allowed('whn', @@ -758,11 +808,16 @@ ENDENTERKEY } elsif ($access eq 'B') { $furl = '/adm/navmaps?showOnlyHomework=1'; } - $msg = &mt('Entering [_1] ...', - $env{'course.'.$cdom.'_'.$cnum.'.description'}); - &redirect_user($r, &mt('Entering [_1]', - $env{'course.'.$cdom.'_'.$cnum.'.description'}), - $furl, $msg); + my $title; + if ($env{'request.lti.login'}) { + undef($msg); + } else { + $title = &mt('Entering [_1]', + $env{'course.'.$cdom.'_'.$cnum.'.description'}); + $msg = &mt('Entering [_1] ...', + $env{'course.'.$cdom.'_'.$cnum.'.description'}); + } + &redirect_user($r,$title,$furl,$msg); } return OK; } @@ -1054,7 +1109,11 @@ ENDHEADER # No active roles if ($countactive==0) { - &requestcourse_advice($r,$cattype,$inrole); + my $elapsed = 0; + if ($now && $update) { + $elapsed = $now - $update; + } + &requestcourse_advice($r,$cattype,$inrole,$elapsed); $r->print(''); if ($countfuture) { $r->print(&mt('The following [quant,_1,role,roles] will become active in the future:',$countfuture)); @@ -1240,6 +1299,7 @@ sub gather_roles { my $advanced = $env{'user.adv'}; my $tryagain = $env{'form.tryagain'}; my @ids = &Apache::lonnet::current_machine_ids(); + my (%willtrust,%trustchecked); if (ref($roles_in_env) eq 'HASH') { my %adhocdesc; foreach my $envkey (sort(keys(%{$roles_in_env}))) { @@ -1308,10 +1368,23 @@ sub gather_roles { if (($role eq 'ca') || ($role eq 'aa')) { my $home = &Apache::lonnet::homeserver($trest,$tdom); my $allowed=0; + my $prohibited; foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } if (!$allowed) { $button=0; - $switchserver='otherserver='.$home.'&role='.$trolecode; + unless ($trustchecked{$tdom}) { + if ((&Apache::lonnet::will_trust('othcoau',$env{'user.domain'},$tdom)) && + (&Apache::lonnet::will_trust('coaurem',$tdom,$env{'user.domain'}))) { + $willtrust{$tdom} = 1; + $trustchecked{$tdom} = 1; + } + } + if ($willtrust{$tdom}) { + $switchserver='otherserver='.$home.'&role='.$trolecode; + } else { + $prohibited = 1; + $tremark .= &mt('Session switch required but prohibited.'); + } } #next if ($home eq 'no_host'); $home = &Apache::lonnet::hostname($home); @@ -1320,7 +1393,9 @@ sub gather_roles { ': '.$tdom.'
'. ' '.&mt('Server').': '.$home; $env{'course.'.$tdom.'_'.$trest.'.description'}='ca'; - $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$trest.'/'); + unless ($prohibited) { + $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$trest.'/'); + } $sortkey=$role."$trest:$tdom"; } elsif ($role eq 'au') { # Authors @@ -1588,20 +1663,26 @@ sub print_rolerows { } sub findcourse_advice { - my ($r,$cattype) = @_; + my ($r,$cattype,$elapsed) = @_; my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); if (&Apache::lonnet::auto_run(undef,$env{'user.domain'})) { - $r->print(&mt('If you were expecting to see an active role listed for a particular course in the [_1] domain, it may be missing for one of the following reasons:',$domdesc).' + $r->print('

'.&mt('If you were expecting to see an active role listed for a particular course in the [_1] domain, it may be missing for one of the following reasons:',$domdesc).'

'); +
  • '.&mt('Automated enrollment added you to the course in the time since you last logged-in.').' '.&mt('If that is the case you can use the "Check for changes" link in the gray Functions bar to update the list of your available course roles.').'
  • +

    '); } else { - $r->print(&mt('If you were expecting to see an active role listed for a particular course, that course may not have been created yet.').'
    '); + $r->print('

    '.&mt('If you were expecting to see an active role listed for a particular course, that course may not have been created yet.').'

    '); + if ($elapsed > 600) { + $r->print('

    '.&mt('You may also have been assigned to a course in the time since you last logged-in, or checked for changes'). + '
    '. + &mt('If that is the case you can use the "Check for changes" link in the gray Functions bar to update the list of your available course roles.').'

    '); + } } if (($cattype eq 'std') || ($cattype eq 'domonly')) { $r->print('

    '.&mt('Self-Enrollment').'

    '. @@ -1613,7 +1694,7 @@ sub findcourse_advice { } sub requestcourse_advice { - my ($r,$cattype,$inrole) = @_; + my ($r,$cattype,$inrole,$elapsed) = @_; my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); my (%can_request,%request_doms,$output); @@ -1674,7 +1755,7 @@ sub requestcourse_advice { } else { $r->print('

    '.&mt('Currently no active roles, courses or communities').'

    '); } - &findcourse_advice($r,$cattype); + &findcourse_advice($r,$cattype,$elapsed); } return; } @@ -2095,9 +2176,9 @@ sub adhoc_customroles_row { if (scalar(keys(%{$domdefaults{'adhocroles'}})) > 0) { return &Apache::loncommon::continue_data_table_row() .' ' - .&mt('[_1]Ad hoc[_2] course/community roles in domain [_3] --', + .&mt('[_1]Ad hoc[_2] course/community roles in domain [_3]', '','',$dhdom) - .' '.&courselink($dhdom,$rowtype,$role); + .' -- '.&courselink($dhdom,$rowtype,$role); } } return; @@ -3043,6 +3124,84 @@ sub get_queued { $output.'
    '; } +sub process_lti { + my ($r,$cdom,$cnum) = @_; + my %lti = &Apache::lonnet::get_domain_lti($cdom,'provider'); + my $uriscope = &LONCAPA::ltiutils::lti_provider_scope($env{'request.lti.uri'}, + $cdom,$cnum); + my $lonhost = $r->dir_config('lonHostID'); + my $internet_names = &Apache::lonnet::get_internet_names($lonhost); + if ($env{'request.lti.rosterid'} && + $env{'request.lti.rosterurl'}) { + if (ref($lti{$env{'request.lti.login'}}) eq 'HASH') { + if ($lti{$env{'request.lti.login'}}{'roster'}) { + my @lcroles = ('in','ta','ep','st'); + my @possibleroles; + foreach my $role (@lcroles) { + if (&Apache::lonnet::allowed('c'.$role,"$cdom/$cnum")) { + push(@possibleroles,$role); + } + } + my $owner = $env{'course.'.$cdom.'_'.$cnum.'.internal.courseowner'}; + if ($owner eq $env{'user.name'}.':'.$env{'user.domain'}) { + my $crstype = &Apache::loncommon::course_type($cdom.'_'.$cnum); + if ($crstype eq 'Community') { + unshift(@possibleroles,'co'); + } else { + unshift(@possibleroles,'cc'); + } + } + if (@possibleroles) { + push(@{$rosterupdates},{cid => $cdom.'_'.$cnum, + lti => $env{'request.lti.login'}, + ltiref => $lti{$env{'request.lti.login'}}, + id => $env{'request.lti.rosterid'}, + url => $env{'request.lti.rosterurl'}, + sourcecrs => $env{'request.lti.sourcecrs'}, + uriscope => $uriscope, + possroles => \@possibleroles, + intdoms => $internet_names, + }); + unless ($registered_cleanup) { + my $handlers = $r->get_handlers('PerlCleanupHandler'); + $r->set_handlers('PerlCleanupHandler' => + [\<ienroll,@{$handlers}]); + $registered_cleanup=1; + } + } + } + } + } + if ($env{'request.lti.passbackid'} && + $env{'request.lti.passbackurl'}) { + if (ref($lti{$env{'request.lti.login'}}) eq 'HASH') { + if ($lti{$env{'request.lti.login'}}{'passback'}) { + my ($pbnum,$error) = + &LONCAPA::ltiutils::store_passbackurl($env{'request.lti.login'}, + $env{'request.lti.passbackurl'}, + $cdom,$cnum); + if ($pbnum eq '') { + $pbnum = $env{'request.lti.passbackurl'}; + } + &Apache::lonnet::put('nohist_'.$cdom.'_'.$cnum.'_passback', + {"$uriscope\0$env{'request.lti.sourcecrs'}\0$env{'request.lti.login'}" => + "$pbnum\0$env{'request.lti.passbackid'}"}); + } + } + } + return; +} + +sub ltienroll { + if (ref($rosterupdates) eq 'ARRAY') { + foreach my $item (@{$rosterupdates}) { + if (ref($item) eq 'HASH') { + &LONCAPA::ltiutils::batchaddroster($item); + } + } + } +} + 1; __END__