--- loncom/interface/lonuserutils.pm 2023/12/10 04:31:41 1.184.4.10.2.6 +++ loncom/interface/lonuserutils.pm 2022/12/01 01:28:26 1.213 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.184.4.10.2.6 2023/12/10 04:31:41 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.213 2022/12/01 01:28:26 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -50,6 +50,7 @@ use strict; use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon; +use Apache::loncoursequeueadmin; use Apache::lonlocal; use Apache::longroup; use HTML::Entities; @@ -103,7 +104,7 @@ sub modifystudent { sub modifyuserrole { my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass, $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role, - $end,$start,$checkid,$inststatus,$emptyok) = @_; + $end,$start,$checkid,$inststatus) = @_; my ($scope,$userresult,$authresult,$roleresult,$idresult); if ($setting eq 'course' || $context eq 'course') { $scope = '/'.$cid; @@ -134,25 +135,6 @@ sub modifyuserrole { generation => $gene, id => $uid, ); - - # When "Update ID in user's course(s)" and "Force change of existing ID" - # checkboxes both checked, prevent replacement of name information - # in classlist.db file(s) for the user's course(s) with blank(s), - # in the case where the uploaded csv file was without column(s) for - # the particular field. Fields are: First Name, Middle Names/Initials, - # Last Name (or the composite: Last Name, First Names), and Generation. - - my %emptyallowed; - if ((ref($emptyok) eq 'HASH') && (keys(%{$emptyok}) > 0)) { - %emptyallowed = %{$emptyok}; - } - foreach my $field (keys(%userupdate)) { - if ($userupdate{$field} eq '') { - unless ($emptyallowed{$field}) { - delete($userupdate{$field}); - } - } - } $idresult = &propagate_id_change($uname,$udom,\%userupdate); } } @@ -172,6 +154,560 @@ sub modifyuserrole { return ($userresult,$authresult,$roleresult,$idresult); } +sub role_approval { + my ($dom,$context,$process_by,$notifydc) = @_; + if (ref($process_by) eq 'HASH') { + my %domconfig = &Apache::lonnet::get_dom('configuration',['privacy'],$dom); + if (ref($domconfig{'privacy'}) eq 'HASH') { + if (ref($notifydc) eq 'ARRAY') { + if ($domconfig{'privacy'}{'notify'} ne '') { + @{$notifydc} = split(/,/,$domconfig{'privacy'}{'notify'}); + } + } + if (ref($domconfig{'privacy'}{'approval'}) eq 'HASH') { + my %approvalconf = %{$domconfig{'privacy'}{'approval'}}; + foreach my $key ('instdom','extdom') { + if (ref($approvalconf{$key}) eq 'HASH') { + if (keys(%{$approvalconf{$key}})) { + $process_by->{$key} = $approvalconf{$key}{$context}; + } + } + } + } + } + } + return; +} + +sub get_instdoms { + my ($udom,$instdoms) = @_; + return unless (ref($instdoms) eq 'ARRAY'); + my @intdoms; + my %iphost = &Apache::lonnet::get_iphost(); + my $primary_id = &Apache::lonnet::domain($udom,'primary'); + my $primary_ip = &Apache::lonnet::get_host_ip($primary_id); + if (ref($iphost{$primary_ip}) eq 'ARRAY') { + foreach my $id (@{$iphost{$primary_ip}}) { + my $intdom = &Apache::lonnet::internet_dom($id); + unless(grep(/^\Q$intdom\E$/,@intdoms)) { + push(@intdoms,$intdom); + } + } + } + foreach my $ip (keys(%iphost)) { + if (ref($iphost{$ip}) eq 'ARRAY') { + foreach my $id (@{$iphost{$ip}}) { + my $location = &Apache::lonnet::internet_dom($id); + if ($location) { + if (grep(/^\Q$location\E$/,@intdoms)) { + my $dom = &Apache::lonnet::host_domain($id); + unless (grep(/^\Q$dom\E/,@{$instdoms})) { + push(@{$instdoms},$dom); + } + } + } + } + } + } + return; +} + +sub restricted_dom { + my ($context,$key,$udom,$uname,$role,$start,$end,$cdom,$cnum,$csec,$credits, + $process_by,$instdoms,$got_role_approvals,$got_instdoms,$reject,$pending, + $notifydc,$status,$unauthorized,$currqueued) = @_; + return if ($udom eq $cdom); + return unless ((ref($process_by) eq 'HASH') && (ref($instdoms) eq 'HASH') && + (ref($got_role_approvals) eq 'HASH') && (ref($got_instdoms) eq 'HASH') && + (ref($reject) eq 'HASH') && (ref($pending) eq 'HASH') && + (ref($notifydc) eq 'HASH') && (ref($status) eq 'HASH') && + (ref($unauthorized) eq 'HASH') && (ref($currqueued) eq 'HASH')); + my (%approval,@notify,$gotdata,$skip); + if (ref($got_role_approvals->{$context}) eq 'HASH') { + if ($got_role_approvals->{$context}{$udom}) { + $gotdata = 1; + if (ref($process_by->{$context}{$udom}) eq 'HASH') { + %approval = %{$process_by->{$context}{$udom}}; + } + } + } + unless ($gotdata) { + &role_approval($udom,$context,\%approval,\@notify); + $process_by->{$context} = { + $udom => \%approval, + }; + $got_role_approvals->{$context} = { + $udom => 1, + }; + $notifydc->{$udom} = \@notify; + } + if (ref($process_by->{$context}) eq 'HASH') { + if (ref($process_by->{$context}{$udom}) eq 'HASH') { + my @inst; + if ($got_instdoms->{$udom}) { + if (ref($instdoms->{$udom}) eq 'ARRAY') { + @inst = @{$instdoms->{$udom}}; + } + } else { + &get_instdoms(\@inst); + $instdoms->{$udom} = \@inst; + $got_instdoms->{$udom} = 1; + } + if (grep(/^\Q$cdom\E$/,@inst)) { + if (exists($approval{'instdom'})) { + my $rule = $approval{'instdom'}; + if (($rule eq 'none') || ($rule eq 'user') || ($rule eq 'domain')) { + my ($id,$currstatus,$curradj) = &get_othdomreq_status($key,$uname,$udom,$role,$cdom,$cnum,$csec); + if (($currstatus ne '') && ($curradj eq $rule)) { + $status->{$key}->{$uname.':'.$udom} = $currstatus; + } + if ($rule eq 'none') { + $reject->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + }; + $skip = 1; + } elsif (($rule eq 'user') || ($rule eq 'domain')) { + if ($curradj eq $rule) { + unless ($currstatus eq 'approved') { + if ($currstatus eq 'rejected') { + $unauthorized->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + }; + } elsif ($currstatus eq 'pending') { + $currqueued->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + adj => $rule, + }; + } + $skip = 1; + } + } else { + $pending->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + start => $start, + end => $end, + adj => $rule, + }; + if (($role eq 'st') && ($credits ne '')) { + $pending->{$key}->{$uname.':'.$udom}->{'credits'} = $credits; + } + $skip = 1; + } + } + } + } + } elsif (exists($approval{'extdom'})) { + my $rule = $approval{'extdom'}; + if (($rule eq 'none') || ($rule eq 'user') || ($rule eq 'domain')) { + my ($id,$currstatus,$curradj) = &get_othdomreq_status($key,$uname,$udom,$role,$cdom,$cnum,$csec); + if (($currstatus ne '') && ($curradj eq $rule)) { + $status->{$key}->{$uname.':'.$udom} = $currstatus; + } + if ($rule eq 'none') { + $reject->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + }; + $skip = 1; + } elsif (($rule eq 'user') || ($rule eq 'domain')) { + if ($curradj eq $rule) { + unless ($currstatus eq 'approved') { + if ($currstatus eq 'rejected') { + $unauthorized->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + }; + } elsif ($currstatus eq 'pending') { + $currqueued->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + adj => $rule, + }; + } + $skip = 1; + } + } else { + $pending->{$key}->{$uname.':'.$udom} = { + cdom => $cdom, + cnum => $cnum, + csec => $csec, + udom => $udom, + uname => $uname, + role => $role, + start => $start, + end => $end, + adj => $rule, + }; + if (($role eq 'st') && ($credits ne '')) { + $pending->{$key}->{$uname.':'.$udom}->{'credits'} = $credits; + } + $skip = 1; + } + } + } + } + } + } + return $skip; +} + +sub get_othdomreq_status { + my ($key,$uname,$udom,$role,$cdom,$cnum,$csec) = @_; + my $id = $uname.':'.$udom.':'.$role; + my ($dbnum,$currstatus,$curradj); + if (($role eq 'ca') || ($role eq 'aa')) { + $dbnum = $cnum; + } elsif ($key eq $cdom.'_'.$role) { + $dbnum = &Apache::lonnet::get_domainconfiguser($cdom); + } else { + $id .= ':'.$csec; + $dbnum = $cnum; + } + my $statusid = 'status&'.$id; + my %curr = &Apache::lonnet::get('nohist_othdomqueued',[$id,$statusid],$cdom,$dbnum); + if (ref($curr{$id}) eq 'HASH') { + $curradj = $curr{$id}{'adj'}; + } + $currstatus = $curr{$statusid}; + return ($id,$currstatus,$curradj); +} + +sub print_roles_rejected { + my ($context,$reject,$unauthorized) = @_; + return unless ((ref($reject) eq 'HASH') || (ref($unauthorized) eq 'HASH')); + my $output; + if (keys(%{$reject}) > 0) { + $output = '

'. + &mt("The following roles could not be assigned because the user is from another domain, and that domain's policies disallow it").'

'; + } + if (keys(%{$unauthorized}) > 0) { + $output = '

'. + &mt("The following roles could not be assigned because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain, and approval has been withheld.").'

'; + } + return $output; +} + +sub print_roles_queued { + my ($context,$pending,$notifydc,$currqueued) = @_; + return unless ((ref($pending) eq 'HASH') && (ref($notifydc) eq 'HASH') && + (ref($currqueued) eq 'HASH')); + my $output; + if (keys(%{$pending}) > 0) { + my $now = time; + $output = '

'. + &mt("The following role assignments have been queued because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain").'

'; + if (keys(%touser)) { + foreach my $key (keys(%touser)) { + my ($uname,$udom) = split(/:/,$touser{$key}); + if (&Apache::lonnet::put('nohist_queuedrolereqs',$touser{$key},$udom,$uname) eq 'ok') { + my $owndomdesc = &Apache::lonnet::domain($udom); + &Apache::loncoursequeueadmin::send_selfserve_notification($uname.':'.$udom, + '','',$owndomdesc,$now,'othdomroleuser',$requester); + } + } + } + if (keys(%todom)) { + foreach my $dom (keys(%todom)) { + if (ref($todom{$dom}) eq 'HASH') { + my $confname = &Apache::lonnet::get_domainconfiguser($dom); + if (&Apache::lonnet::put('nohist_queuedrolereqs',$todom{$dom},$dom,$confname) eq 'ok') { + if (ref($notifydc->{$dom}) eq 'ARRAY') { + if (@{$notifydc->{$dom}} > 0) { + my $notifylist = join(',',@{$notifydc->{$dom}}); + &Apache::loncoursequeueadmin::send_selfserve_notification($notifylist, + '','','',$now,'othdomroledc',$requester); + } + } + } + } + } + } + if (keys(%crsqueue)) { + foreach my $key (keys(%crsqueue)) { + my ($cdom,$cnum) = split(/_/,$key); + if (ref($crsqueue{$key}) eq 'HASH') { + &Apache::lonnet::put('nohist_othdomqueued',$crsqueue{$key},$cdom,$cnum); + } + } + } + if (keys(%caqueue)) { + foreach my $key (keys(%caqueue)) { + my ($auname,$audom) = split(/:/,$key); + if (ref($caqueue{$key}) eq 'HASH') { + &Apache::lonnet::put('nohist_othdomqueued',$caqueue{$key},$audom,$auname); + } + } + } + if (keys(%domqueue)) { + my $confname = &Apache::lonnet::get_domainconfiguser($env{'request.role.domain'}); + &Apache::lonnet::put('nohist_othdomqueued',\%domqueue,$env{'request.role.domain'},$confname); + } + } + if (keys(%{$currqueued}) > 0) { + $output = '

'. + &mt("The following role assignments were already queued because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain").'

'; + } + return $output; +} + sub propagate_id_change { my ($uname,$udom,$user) = @_; my (@types,@roles); @@ -529,7 +1065,7 @@ END "; } elsif ($mode eq 'modifycourse') { $auth_checks .= " - if ((current.argfield !== null) && (current.argfield !== undefined) && (current.argfield !== '') && (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '')) { + if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') { "; } if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) { @@ -571,6 +1107,7 @@ END case 'loc': alertmsg = ''; break; + case 'lti': default: alertmsg = ''; } @@ -928,6 +1465,7 @@ sub print_upload_manager_footer { my $krbform = &Apache::loncommon::authform_kerberos(%param); my $intform = &Apache::loncommon::authform_internal(%param); my $locform = &Apache::loncommon::authform_local(%param); + my $ltiform = &Apache::loncommon::authform_lti(%param); my $date_table = &date_setting_table(undef,undef,$context,undef, $formname,$permission,$crstype); @@ -956,7 +1494,7 @@ sub print_upload_manager_footer { &Apache::loncommon::help_open_topic('Auth_Options'). "

\n"; } - $Str .= &set_login($defdom,$krbform,$intform,$locform); + $Str .= &set_login($defdom,$krbform,$intform,$locform,$ltiform); my ($home_server_pick,$numlib) = &Apache::loncommon::home_server_form_item($defdom,'lcserver', @@ -973,8 +1511,14 @@ sub print_upload_manager_footer { &Apache::lonhtmlcommon::row_closure(); } + my ($trusted,$untrusted); + if ($context eq 'course') { + ($trusted,$untrusted) = &Apache::lonnet::trusted_domains('enroll',$defdom); + } elsif ($context eq 'author') { + ($trusted,$untrusted) = &Apache::lonnet::trusted_domains('othcoau',$defdom); + } $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain')) - .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1) + .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1,undef,$trusted,$untrusted) .&Apache::lonhtmlcommon::row_closure(); $Str .= &Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates')) @@ -1591,10 +2135,11 @@ sub my_custom_roles { my %rolehash=&Apache::lonnet::dump('roles',$udom,$uname); foreach my $key (keys(%rolehash)) { if ($key=~/^rolesdef\_(\w+)$/) { + my $role = $1; if ($crstype eq 'Community') { next if ($rolehash{$key} =~ /bre\&S/); } - $returnhash{$1}=$1; + $returnhash{$role}=$role; } } return %returnhash; @@ -4178,25 +4723,9 @@ sub upfile_drop_add { $fieldstype{$field.'_choice'} = 'scalar'; } &Apache::loncommon::store_course_settings('enrollment_upload',\%fieldstype); - my ($cid,$crstype,$setting,$crsdom,$crsnum,$oldcrsuserdoms,%emptyok); + my ($cid,$crstype,$setting,$crsdom,$crsnum); if ($context eq 'domain') { $setting = $env{'form.roleaction'}; - if (exists($fields{'names'})) { - map { $emptyok{$_} = 1; } ('lastname','firstname','middlename'); - } else { - if (exists($fields{'lname'})) { - $emptyok{'lastname'} = 1; - } - if (exists($fields{'fname'})) { - $emptyok{'firstname'} = 1; - } - if (exists($fields{'mname'})) { - $emptyok{'middlename'} = 1; - } - } - if (exists($fields{'gen'})) { - $emptyok{'generation'} = 1; - } } if ($env{'request.course.id'} ne '') { $cid = $env{'request.course.id'}; @@ -4209,11 +4738,6 @@ sub upfile_drop_add { $crstype = &Apache::loncommon::course_type($cid); $crsdom = $env{'form.dcdomain'}; $crsnum = $env{'form.dccourse'}; - if (exists($env{'course.'.$cid.'.internal.userdomains'})) { - $oldcrsuserdoms = 1; - } - my %coursedesc = &Apache::lonnet::coursedescription($cid,{ one_time => 1 }); - $env{'course.'.$cid.'.internal.userdomains'} = $coursedesc{'internal.userdomains'}; } } my ($startdate,$enddate) = &get_dates_from_form(); @@ -4224,7 +4748,47 @@ sub upfile_drop_add { my $defdom=$env{'request.role.domain'}; my $domain; if ($env{'form.defaultdomain'} ne '') { - $domain = $env{'form.defaultdomain'}; + if (($context eq 'course') || ($setting eq 'course')) { + if ($env{'form.defaultdomain'} eq $crsdom) { + $domain = $env{'form.defaultdomain'}; + } else { + if (&Apache::lonnet::will_trust('enroll',$crsdom,$env{'form.defaultdomain'})) { + $domain = $env{'form.defaultdomain'}; + } else { + $r->print(''.&mt('Error').': '. + &mt('Enrollment of users not permitted for specified default domain: [_1].', + &Apache::lonnet::domain($env{'form.defaultdomain'},'description')).''); + return 'untrusted'; + } + } + } elsif ($context eq 'author') { + if ($env{'form.defaultdomain'} eq $defdom) { + $domain = $env{'form.defaultdomain'}; + } else { + if ((&Apache::lonnet::will_trust('othcoau',$defdom,$env{'form.defaultdomain'})) && + (&Apache::lonnet::will_trust('coaurem',$env{'form.defaultdomain'},$defdom))) { + $domain = $env{'form.defaultdomain'}; + } else { + $r->print(''.&mt('Error').': '. + &mt('Addition of users not permitted for specified default domain: [_1].', + &Apache::lonnet::domain($env{'form.defaultdomain'},'description')).''); + return 'untrusted'; + } + } + } elsif (($context eq 'domain') && ($setting eq 'domain')) { + if ($env{'form.defaultdomain'} eq $defdom) { + $domain = $env{'form.defaultdomain'}; + } else { + if (&Apache::lonnet::will_trust('domroles',$defdom,$env{'form.defaultdomain'})) { + $domain = $env{'form.defaultdomain'}; + } else { + $r->print(''.&mt('Error').': '. + &mt('Addition of users not permitted for specified default domain: [_1].', + &Apache::lonnet::domain($env{'form.defaultdomain'},'description')).''); + return 'untrusted'; + } + } + } } else { $domain = $defdom; } @@ -4236,7 +4800,6 @@ sub upfile_drop_add { if (! exists($home_servers{$desiredhost})) { $r->print('

'.&mt('Error').': '. &mt('Invalid home server specified').'

'); - $r->print(&Apache::loncommon::end_page()); return 'invalidhome'; } } @@ -4264,6 +4827,8 @@ sub upfile_drop_add { if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) { $genpwd=$env{'form.locarg'}; } + } elsif ($env{'form.login'} eq 'lti') { + $amode='lti'; } if ($amode =~ /^krb/) { if (! defined($genpwd) || $genpwd eq '') { @@ -4357,6 +4922,8 @@ sub upfile_drop_add { $r->print('

'.&mt('Adding/Modifying Users')."

\n

\n"); } $r->rflush; + my (%got_role_approvals,%got_instdoms,%process_by,%instdoms, + %pending,%reject,%notifydc,%status,%unauthorized,%currqueued); my %counts = ( user => 0, @@ -4416,6 +4983,7 @@ sub upfile_drop_add { my (%existinguser,%userinfo,%disallow,%rulematch,%inst_results,%alerts,%checkuname, %showpasswdrules,$haspasswdmap); my $counter = -1; + my (%willtrust,%trustchecked); foreach my $line (@userdata) { $counter ++; my @secs; @@ -4463,6 +5031,28 @@ sub upfile_drop_add { '"'.$entries{$fields{'domain'}}.'"', $fname,$mname,$lname,$gen); next; + } elsif ($entries{$fields{'domain'}} ne $domain) { + my $possdom = $entries{$fields{'domain'}}; + if ($context eq 'course' || $setting eq 'course') { + unless ($trustchecked{$possdom}) { + $willtrust{$possdom} = &Apache::lonnet::will_trust('enroll',$domain,$possdom); + $trustchecked{$possdom} = 1; + } + } elsif ($context eq 'author') { + unless ($trustchecked{$possdom}) { + $willtrust{$possdom} = &Apache::lonnet::will_trust('othcoau',$domain,$possdom); + } + if ($willtrust{$possdom}) { + $willtrust{$possdom} = &Apache::lonnet::will_trust('coaurem',$possdom,$domain); + } + } + unless ($willtrust{$possdom}) { + $disallow{$counter} = + &mt('Unacceptable domain [_1] for user [_2] [_3] [_4] [_5]', + '"'.$possdom.'"', + $fname,$mname,$lname,$gen); + next; + } } my $username = $entries{$fields{'username'}}; my $userdomain = $entries{$fields{'domain'}}; @@ -4647,7 +5237,7 @@ sub upfile_drop_add { &mt('The user does not already exist, and you may not create a new user in a different domain.'); next; } else { - unless ($password || $env{'form.login'} eq 'loc') { + unless (($password ne '') || ($env{'form.login'} eq 'loc') || ($env{'form.login'} eq 'lti')) { $disallow{$counter} = &mt('[_1]: This is a new user but no default password was provided, and the authentication type requires one.', ''.$username.''); @@ -4866,6 +5456,17 @@ sub upfile_drop_add { $sec = $secs[0]; } } + if ($userdomain ne $env{'request.role.domain'}) { + my $item = "/$crsdom/$crsnum" ; + if ($sec ne '') { + $item .= "/$sec"; + } + $item .= '_st'; + next if (&restricted_dom($context,$item,$userdomain,$username,$role,$startdate, + $enddate,$crsdom,$crsnum,$sec,$credits,\%process_by, + \%instdoms,\%got_role_approvals,\%got_instdoms,\%reject, + \%pending,\%notifydc,\%status,\%unauthorized,\%currqueued)); + } &modifystudent($userdomain,$username,$cid,$sec, $desiredhost,$context); $roleresult = @@ -4877,16 +5478,34 @@ sub upfile_drop_add { '',$context,$inststatus,$credits); $userresult = $roleresult; } else { - if ($role ne '') { + my $possrole; + if ($role ne '') { if ($context eq 'course' || $setting eq 'course') { if ($customroles{$role}) { $role = 'cr_'.$env{'user.domain'}.'_'. $env{'user.name'}.'_'.$role; } - if (($role ne 'cc') && ($role ne 'co')) { + $possrole = $role; + if ($possrole =~ /^cr_/) { + $possrole =~ s{_}{/}g; + } + if (($role ne 'cc') && ($role ne 'co')) { if (@secs > 1) { $multiple = 1; + my $prefix = "/$crsdom/$crsnum"; foreach my $sec (@secs) { + if ($userdomain ne $env{'request.role.domain'}) { + my $item = $prefix; + if ($sec ne '') { + $item .= "/$sec"; + } + $item .= '_'.$possrole; + next if (&restricted_dom($context,$item,$userdomain,$username,$possrole, + $startdate,$enddate,$crsdom,$crsnum,$sec, + $credits,\%process_by,\%instdoms,\%got_role_approvals, + \%got_instdoms,\%reject,\%pending,\%notifydc, + \%status,\%unauthorized,\%currqueued)); + } ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) = &modifyuserrole($context,$setting, $changeauth,$cid,$userdomain,$username, @@ -4900,9 +5519,22 @@ sub upfile_drop_add { $singlesec = $secs[0]; } } + } else { + $possrole = $role; } } if (!$multiple) { + if (($userdomain ne $env{'request.role.domain'}) && ($role ne '')) { + my $item = "/$crsdom/$crsnum"; + if ($singlesec ne '') { + $item .= "/$singlesec"; + } + $item .= '_'.$possrole; + next if (&restricted_dom($context,$item,$userdomain,$username,$possrole,$startdate,$enddate, + $crsdom,$crsnum,$singlesec,$credits,\%process_by,\%instdoms, + \%got_role_approvals,\%got_instdoms,\%reject,\%pending,\%notifydc, + \%status,\%unauthorized,\%currqueued)); + } ($userresult,$authresult,$roleresult,$idresult) = &modifyuserrole($context,$setting, $changeauth,$cid,$userdomain,$username, @@ -4910,7 +5542,7 @@ sub upfile_drop_add { $mname,$lname,$gen,$singlesec, $env{'form.forceid'},$desiredhost, $email,$role,$enddate,$startdate, - $checkid,$inststatus,\%emptyok); + $checkid,$inststatus); } } if ($multiple) { @@ -4932,13 +5564,6 @@ sub upfile_drop_add { } # end of loop $r->print(''); &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); - if (($context eq 'domain') && ($setting eq 'course')) { - unless ($oldcrsuserdoms) { - if (exists($env{'course.'.$cid.'.internal.userdomains'})) { - delete($env{'course.'.$cid.'.internal.userdomains'}); - } - } - } } # Flush the course logs so reverse user roles immediately updated $r->register_cleanup(\&Apache::lonnet::flushcourselogs); @@ -4959,6 +5584,12 @@ sub upfile_drop_add { } $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules)); $r->print(&passwdrule_alerts($domain,\%showpasswdrules)); + if ((keys(%reject)) || (keys(%unauthorized))) { + $r->print(&print_roles_rejected($context,\%reject,\%unauthorized)); + } + if ((keys(%pending)) || (keys(%currqueued))) { + $r->print(&print_roles_queued($context,\%pending,\%notifydc,\%currqueued)); + } ##################################### # Display list of students to drop # ##################################### @@ -5152,7 +5783,8 @@ sub update_user_list { if ($context eq 'course') { $crstype = &Apache::loncommon::course_type(); } - my @changelist; + my (@changelist,%got_role_approvals,%got_instdoms,%process_by,%instdoms, + %pending,%reject,%notifydc,%status,%unauthorized,%currqueued); if ($choice eq 'drop') { @changelist = &Apache::loncommon::get_env_multiple('form.droplist'); } else { @@ -5182,7 +5814,7 @@ sub update_user_list { foreach my $item (@changelist) { my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype, @sections,$scopestem,$singlesec,$showsecs,$warn_singlesec, - $nothingtodo,$keepnosection,$credits,$instsec); + $nothingtodo,$keepnosection,$credits,$instsec,$cdom,$cnum); if ($choice eq 'drop') { ($uname,$udom,$sec) = split(/:/,$item,-1); $role = 'st'; @@ -5199,6 +5831,8 @@ sub update_user_list { split(/\:/,$item,8); $instsec = &unescape($instsec); $cid = $env{'request.course.id'}; + $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; $scopestem = '/'.$cid; $scopestem =~s/\_/\//g; if ($sec eq '') { @@ -5209,15 +5843,20 @@ sub update_user_list { } elsif ($context eq 'author') { ($uname,$udom,$role) = split(/\:/,$item,-1); $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'}; + $cdom = $env{'user.domain'}; + $cnum = $env{'user.name'}; } elsif ($context eq 'domain') { if ($setting eq 'domain') { ($role,$uname,$udom) = split(/\:/,$item,-1); $scope = '/'.$env{'request.role.domain'}.'/'; + $cdom = $env{'request.role.domain'}; } elsif ($setting eq 'author') { ($uname,$udom,$role,$scope) = split(/\:/,$item); + (undef,$cdom,$cnum) = split(/\//,$scope); } elsif ($setting eq 'course') { ($uname,$udom,$role,$cid,$sec,$type,$locktype,$credits,$instsec) = split(/\:/,$item,9); + ($cdom,$cnum) = split('_',$cid); $instsec = &unescape($instsec); $scope = '/'.$cid; $scope =~s/\_/\//g; @@ -5259,7 +5898,12 @@ sub update_user_list { $start = $startdate; $end = $enddate; } + my $id = $scope.'_'.$role; if ($choice eq 'reenable') { + next if (&restricted_dom($context,$id,$udom,$uname,$role,$now,$end,$cdom,$cnum, + $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals, + \%got_instdoms,\%reject,\%pending,\%notifydc, + \%status,\%unauthorized,\%currqueued)); if ($role eq 'st') { $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec); } else { @@ -5268,6 +5912,10 @@ sub update_user_list { $now,'','',$context); } } elsif ($choice eq 'activate') { + next if (&restricted_dom($context,$id,$udom,$uname,$role,$now,$end,$cdom,$cnum, + $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals, + \%got_instdoms,\%reject,\%pending,\%notifydc, + \%status,\%unauthorized,\%currqueued)); if ($role eq 'st') { $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec); } else { @@ -5275,6 +5923,10 @@ sub update_user_list { $now,'','',$context); } } elsif ($choice eq 'chgdates') { + next if (&restricted_dom($context,$id,$udom,$uname,$role,$start,$end,$cdom,$cnum, + $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals, + \%got_instdoms,\%reject,\%pending,\%notifydc, + \%status,\%unauthorized,\%currqueued)); if ($role eq 'st') { $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec); } else { @@ -5484,6 +6136,12 @@ sub update_user_list { $r->print(&make_dates_default($startdate,$enddate,$context,$crstype)); } } + if ((keys(%reject)) || (keys(%unauthorized))) { + $r->print(&print_roles_rejected($context,\%reject,\%unauthorized)); + } + if ((keys(%pending)) || (keys(%currqueued))) { + $r->print(&print_roles_queued($context,\%pending,\%notifydc,\%currqueued)); + } my $linktext = &mt('Display User Lists'); if ($choice eq 'drop') { $linktext = &mt('Display current class roster'); @@ -5567,7 +6225,7 @@ END } sub set_login { - my ($dom,$authformkrb,$authformint,$authformloc) = @_; + my ($dom,$authformkrb,$authformint,$authformloc,$authformlti) = @_; my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom); my $response; my ($authnum,%can_assign) = @@ -5589,6 +6247,11 @@ sub set_login { ''.$authformloc.''. &Apache::loncommon::end_data_table_row()."\n"; } + if ($can_assign{'lti'}) { + $response .= &Apache::loncommon::start_data_table_row(). + ''.$authformlti.''. + &Apache::loncommon::end_data_table_row()."\n"; + } $response .= &Apache::loncommon::end_data_table(); } return $response; @@ -6117,9 +6780,6 @@ sub get_permission { $permission{'selfenrolladmin'} = 1; } } - unless ($permission{'selfenrolladmin'}) { - $permission{'selfenrollview'} = 1; - } } if ($env{'request.course.id'}) { my $user; @@ -6583,7 +7243,7 @@ sub selfenrollment_administration { } } if ($settings{'internal.selfenrollmgrdc'} ne '') { - @in_domain = split(/,/,$settings{'internal.selfenrollmgrdc'}); + my @in_domain = split(/,/,$settings{'internal.selfenrollmgrdc'}); my @diffs = &Apache::loncommon::compare_arrays(\@in_domain,$possconfigs); unless (@diffs) { return (\@in_course,\@in_domain);