--- loncom/auth/lonroles.pm 2008/01/26 21:12:32 1.182 +++ loncom/auth/lonroles.pm 2008/06/04 19:14:20 1.195 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # User Roles Screen # -# $Id: lonroles.pm,v 1.182 2008/01/26 21:12:32 www Exp $ +# $Id: lonroles.pm,v 1.195 2008/06/04 19:14:20 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -106,22 +106,31 @@ sub handler { # ================================================================== Roles Init if ($env{'form.selectrole'}) { + + my $locknum=&Apache::lonnet::get_locks(); + if ($locknum) { return 409; } + if ($env{'form.newrole'}) { $env{'form.'.$env{'form.newrole'}}=1; } if ($env{'request.course.id'}) { + # Check if user is CC trying to select a course role + if ($env{'form.switchrole'}) { + if (!defined($env{'user.role.'.$env{'form.switchrole'}})) { + &adhoc_course_role($then); + } + } my %temp=('logout_'.$env{'request.course.id'} => time); &Apache::lonnet::put('email_status',\%temp); &Apache::lonnet::delenv('user.state.'.$env{'request.course.id'}); } - &Apache::lonnet::appenv("request.course.id" => '', - "request.course.fn" => '', - "request.course.uri" => '', - "request.course.sec" => '', - "request.role" => 'cm', - "request.role.adv" => $env{'user.adv'}, - "request.role.domain" => $env{'user.domain'}); - + &Apache::lonnet::appenv({"request.course.id" => '', + "request.course.fn" => '', + "request.course.uri" => '', + "request.course.sec" => '', + "request.role" => 'cm', + "request.role.adv" => $env{'user.adv'}, + "request.role.domain" => $env{'user.domain'}}); # Check if user is a DC trying to enter a course or author space and needs privs to be created if ($numdc > 0) { foreach my $envkey (keys %env) { @@ -133,24 +142,31 @@ sub handler { } last; } -# Is this a recent ad-hoc CA-role? - if (my ($domain,$coursenum) = - ($envkey =~ m-^form\.ca\./($match_domain)/($match_courseid)$-)) { - if ($dcroles{$domain}) { - &check_privs($domain,$coursenum,$then,$now,'ca'); +# Is this an ad-hoc CA-role? + if (my ($domain,$user) = + ($envkey =~ m-^form\.ca\./($match_domain)/($match_username)$-)) { + # Check if author blocked ca-access + my %blocked=&Apache::lonnet::get('environment',['domcoord.author'],$domain,$user); + if ($blocked{'domcoord.author'} eq 'blocked') { + delete($env{$envkey}); + $env{'user.error.msg'}=':::1:User '.$user.' in domain '.$domain.' blocked domain coordinator access'; + last; } - last; - } -# Is this a new ad-hoc CA-role? - if (my ($domain) = - ($envkey =~ m-^form\.adhocca\./($match_domain)$-)) { if ($dcroles{$domain}) { - my $user=$env{'form.adhoccauname.'.$domain}; - if (!$user) { $user=$env{'form.adhoccaunamerecent.'.$domain} }; - if (($user) && ($user=~/$match_username/)) { - &check_privs($domain,$user,$then,$now,'ca'); - $env{'form.ca./'.$domain.'/'.$user}=1; - } + my ($server_status,$home) = &check_author_homeserver($user,$domain); + if (($server_status eq 'ok') || ($server_status eq 'switchserver')) { + &check_privs($domain,$user,$then,$now,'ca'); + if ($server_status eq 'switchserver') { + my $trolecode = 'ca./'.$domain.'/'.$user; + my $switchserver = '/adm/switchserver?' + .'otherserver='.$home.'&role='.$trolecode; + $r->internal_redirect($switchserver); + } + } else { + delete($env{$envkey}); + } + } else { + delete($env{$envkey}); } last; } @@ -267,10 +283,10 @@ ENDENTERKEY "Role ".$trolecode); &Apache::lonnet::appenv( - 'request.role' => $trolecode, - 'request.role.domain' => $cdom, - 'request.course.sec' => $csec, - 'request.course.groups' => $cgrps); + {'request.role' => $trolecode, + 'request.role.domain' => $cdom, + 'request.course.sec' => $csec, + 'request.course.groups' => $cgrps}); my $tadv=0; if (($cnum) && ($role ne 'ca') && ($role ne 'aa')) { @@ -281,7 +297,7 @@ ENDENTERKEY ($env{'form.orgurl'}!~/^\/adm\/flip/)) { my $dest=$env{'form.orgurl'}; if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; } - &Apache::lonnet::appenv('request.role.adv'=>$tadv); + &Apache::lonnet::appenv({'request.role.adv'=>$tadv}); if (($ferr) && ($tadv)) { &error_page($r,$ferr,$dest); } else { @@ -291,7 +307,7 @@ ENDENTERKEY } else { if (!$env{'request.course.id'}) { &Apache::lonnet::appenv( - "request.course.id" => $cdom.'_'.$cnum); + {"request.course.id" => $cdom.'_'.$cnum}); $furl='/adm/roles?tryagain=1'; $msg= '

'. @@ -300,7 +316,7 @@ ENDENTERKEY '

'.&mt('Please try again.').'

'.$ferr; } if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; } - &Apache::lonnet::appenv('request.role.adv'=>$tadv); + &Apache::lonnet::appenv({'request.role.adv'=>$tadv}); if (($ferr) && ($tadv)) { &error_page($r,$ferr,$furl); @@ -317,6 +333,14 @@ ENDENTERKEY $furl = "/adm/helper/course.initialization.helper"; # Send the user to the course they selected } elsif ($env{'request.course.id'}) { + if ($env{'form.destinationurl'}) { + my $dest = $env{'form.destinationurl'}; + &redirect_user($r,&mt('Entering [_1]', + $env{'course.'.$courseid.'.description'}), + $dest,$msg, + $env{'environment.remotenavmap'}); + return OK; + } if (&Apache::lonnet::allowed('whn', $env{'request.course.id'}) || &Apache::lonnet::allowed('whn', @@ -387,7 +411,7 @@ ENDENTERKEY my $start_page=&Apache::loncommon::start_page('User Roles'); my $standby=&mt('Role selected. Please stand by.'); $standby=~s/\n/\\n/g; - my $noscript=''.&mt('Use of LON-CAPA requires Javascript to be enabled in your web browser.').'
'.&mt('As this is not the case, most functionality in the system will ba unavailable.').'

'; + my $noscript=''.&mt('Use of LON-CAPA requires Javascript to be enabled in your web browser.').'
'.&mt('As this is not the case, most functionality in the system will be unavailable.').'

'; $r->print(<print("

LON-CAPA Access Control

"); + $r->print("

".&mt('LON-CAPA Access Control')."

"); $r->print("
");
 	if ($priv ne '') {
-	    $r->print("Access  : ".&Apache::lonnet::plaintext($priv)."\n");
+            $r->print(&mt('Access  : ').&Apache::lonnet::plaintext($priv)."\n");
 	}
 	if ($fn ne '') {
-	    $r->print("Resource: ".&Apache::lonenc::check_encrypt($fn)."\n");
+            $r->print(&mt('Resource: ').&Apache::lonenc::check_encrypt($fn)."\n");
 	}
 	if ($msg ne '') {
-	    $r->print("Action  : $msg\n");
+            $r->print(&mt('Action  : ').$msg."\n");
 	}
 	$r->print("

"); my $url=$fn; @@ -486,8 +510,12 @@ ENDHEADER my (%roletext,%sortrole,%roleclass); my $countactive=0; + my $countfuture=0; + my $countwill=0; my $inrole=0; my $possiblerole=''; + my %futureroles; + my %roles_nextlogin; foreach $envkey (sort keys %env) { my $button = 1; my $switchserver=''; @@ -524,9 +552,13 @@ ENDHEADER } elsif ($tstatus eq 'future') { $tbg='#FFFF77'; $button=0; + $futureroles{$trolecode} = $tstart.':'.$tend; + $countfuture ++; } elsif ($tstatus eq 'will') { $tbg='#FFAA77'; $tremark.=&mt('Active at next login. '); + $roles_nextlogin{$trolecode} = $tstart.':'.$tend; + $countwill ++; } elsif ($tstatus eq 'expired') { $tbg='#FF7777'; $tfont='#330000'; @@ -649,7 +681,30 @@ ENDHEADER } else { $r->print('

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

'); } - $r->print(''.&Apache::loncommon::end_page()); + &findcourse_advice($r); + $r->print(''); + if ($countfuture) { + $r->print(&mt('The following [quant,_1,role,roles] will become active in the future:',$countfuture)); + my $doheaders = &roletable_headers($r,\%roleclass,\%sortrole, + $nochoose); + &print_rolerows($r,$doheaders,\%roleclass,\%sortrole,\%dcroles, + \%roletext); + my $tremark=''; + my $tfont='#003300'; + if ($env{'request.role'} eq 'cm') { + $r->print(''); + $tremark=&mt('Currently selected. '); + $tfont='#002200'; + } else { + $r->print(''); + } + $r->print(''.&mt('No role specified'). + ''.$tremark. + ' '."\n"); + + $r->print(''); + } + $r->print(&Apache::loncommon::end_page()); return OK; # Is there only one choice? } elsif (($countactive==1) && ($env{'request.role'} eq 'cm')) { @@ -667,21 +722,7 @@ ENDHEADER unless ((!&Apache::lonmenu::show_course()) || ($nochoose)) { $r->print("

".&mt('Select a Course to Enter')."

\n"); } - $r->print('
'); - unless ($nochoose) { $r->print(''); } - $r->print(''."\n"); - my $doheaders=-1; - foreach my $type ('Domain','Construction Space','Course','Unavailable','System') { - my $haverole=0; - foreach my $which (sort {uc($a) cmp uc($b)} (keys(%sortrole))) { - if ($roleclass{$sortrole{$which}} =~ /^\Q$type\E/) { - $haverole=1; - } - } - if ($haverole) { $doheaders++; } - } - + my $doheaders = &roletable_headers($r,\%roleclass,\%sortrole,$nochoose); if ($env{'environment.recentroles'}) { my %recent_roles = &Apache::lonhtmlcommon::get_recent('roles',$env{'environment.recentrolesn'}); @@ -691,8 +732,7 @@ ENDHEADER $output.=$roletext{'user.role.'.$_}; if ($_ =~ m-dc\./($match_domain)/- && $dcroles{$1}) { - $output .= &allcourses_row($1,'recent'). - &allcoauthors_row($1,'recent'); + $output .= &adhoc_roles_row($1,'recent'); } } elsif ($numdc > 0) { unless ($_ =~/^error\:/) { @@ -702,38 +742,18 @@ ENDHEADER } if ($output) { $r->print(""); + &mt('Recent Roles').""); $r->print($output); - $r->print(""); $doheaders ++; } } if ($numdc > 0) { $r->print(&coursepick_jscript()); - $r->print(&Apache::loncommon::coursebrowser_javascript()); - } - foreach my $type ('Construction Space','Domain','Course','Unavailable','System') { - my $output; - foreach my $which (sort {uc($a) cmp uc($b)} (keys(%sortrole))) { - if ($roleclass{$sortrole{$which}} =~ /^\Q$type\E/) { - $output.=$roletext{$sortrole{$which}}; - if ($sortrole{$which} =~ m-dc\./($match_domain)/-) { - if ($dcroles{$1}) { - $output .= &allcourses_row($1,''). - &allcoauthors_row($1,''); - } - } - } - } - if ($output) { - if ($doheaders > 0) { - $r->print("". - ""); - } - $r->print($output); - } + $r->print(&Apache::loncommon::coursebrowser_javascript(). + &Apache::loncommon::authorbrowser_javascript()); } + &print_rolerows($r,$doheaders,\%roleclass,\%sortrole,\%dcroles,\%roletext); my $tremark=''; my $tfont='#003300'; if ($env{'request.role'} eq 'cm') { @@ -746,13 +766,13 @@ ENDHEADER unless ($nochoose) { if ($env{'request.role'} ne 'cm') { $r->print(''); + &mt('Select').'" name="cm" />'); } else { $r->print(''); } } $r->print(''."\n"); $r->print('
 '.&mt('User Role').''.&mt('Extent'). - ''.&mt('Start').''.&mt('End').'
". - &mt('Recent Roles')."
".&mt($type)."
 '.&mt('No role specified'). - ''.$tremark. + ''.$tremark. ' 
'); @@ -766,14 +786,96 @@ ENDHEADER } $r->print(&Apache::lonnet::getannounce()); if ($advanced) { - $r->print('

This is LON-CAPA '. - $r->dir_config('lonVersion').'
'. - ''.&mt('Logout').'

'); + $r->print('

' + .&mt('This is LON-CAPA [_1]',$r->dir_config('lonVersion')) + .'
' + .''.&mt('Logout').'

'); } $r->print(&Apache::loncommon::end_page()); return OK; } +sub roletable_headers { + my ($r,$roleclass,$sortrole,$nochoose) = @_; + my $doheaders; + if ((ref($sortrole) eq 'HASH') && (ref($roleclass) eq 'HASH')) { + $r->print('
'); + if (!$nochoose) { $r->print(''); } + $r->print(''."\n"); + $doheaders=-1; + my @roletypes = &roletypes(); + foreach my $type (@roletypes) { + my $haverole=0; + foreach my $which (sort {uc($a) cmp uc($b)} (keys(%{$sortrole}))) { + if ($roleclass->{$sortrole->{$which}} =~ /^\Q$type\E/) { + $haverole=1; + } + } + if ($haverole) { $doheaders++; } + } + } + return $doheaders; +} + +sub roletypes { + my @types = ('Domain','Construction Space','Course','Unavailable','System'); + return @types; +} + +sub print_rolerows { + my ($r,$doheaders,$roleclass,$sortrole,$dcroles,$roletext) = @_; + if ((ref($roleclass) eq 'HASH') && (ref($sortrole) eq 'HASH')) { + my @types = &roletypes(); + foreach my $type (@types) { + my $output; + foreach my $which (sort {uc($a) cmp uc($b)} (keys(%{$sortrole}))) { + if ($roleclass->{$sortrole->{$which}} =~ /^\Q$type\E/) { + if (ref($roletext) eq 'HASH') { + $output.=$roletext->{$sortrole->{$which}}; + if ($sortrole->{$which} =~ m-dc\./($match_domain)/-) { + if (ref($dcroles) eq 'HASH') { + if ($dcroles->{$1}) { + $output .= &adhoc_roles_row($1,''); + } + } + } + } + } + } + if ($output) { + if ($doheaders > 0) { + $r->print("". + ""); + } + $r->print($output); + } + } + } +} + +sub findcourse_advice { + my ($r) = @_; + my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); + if (&check_autoenroll($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).' +'); + } 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('The [_1]Course Catalog[_2] provides information about all [_3] classes for which LON-CAPA courses have been created.','','',$domdesc).'
'); + $r->print(&mt('You can search the course catalog for courses which permit self-enrollment, if you would like to enroll in a course.').'

'); + return; +} + sub privileges_info { my ($which) = @_; my $output; @@ -874,17 +976,17 @@ sub build_roletext { } elsif ($tstatus eq 'is') { $roletext.=''; + $trolecode."','".$buttonname.'\');" />'; } elsif ($tryagain) { $roletext.= ''; + $trolecode."','".$buttonname.'\');" />'; } elsif ($advanced) { $roletext.= ''; + $trolecode."','".$buttonname.'\');" />'; } else { $roletext.=' '; } @@ -905,6 +1007,23 @@ sub build_roletext { return $roletext; } +sub check_author_homeserver { + my ($uname,$udom)=@_; + if (($uname eq '') || ($udom eq '')) { + return ('fail',''); + } + my $home = &Apache::lonnet::homeserver($uname,$udom); + if (&Apache::lonnet::host_domain($home) ne $udom) { + return ('fail',$home); + } + my @ids=&Apache::lonnet::current_machine_ids(); + if (grep(/^\Q$home\E$/,@ids)) { + return ('ok',$home); + } else { + return ('switchserver',$home); + } +} + sub check_privs { my ($cdom,$cnum,$then,$now,$checkrole) = @_; my $cckey = 'user.role.'.$checkrole.'./'.$cdom.'/'.$cnum; @@ -940,8 +1059,71 @@ sub check_fordc { return $numdc; } +sub adhoc_course_role { + my ($then) = @_; + my ($cdom,$cnum); + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if (&check_forcc($cdom,$cnum,$then)) { + my $setprivs; + if (!defined($env{'user.role.'.$env{'form.selectrole'}})) { + $setprivs = 1; + } else { + my ($start,$end) = split(/\./,$env{'user.role.'.$env{'form.selectrole'}}); + if (($start && ($start>$then || $start == -1)) || + ($end && $end<$then)) { + $setprivs = 1; + } + } + if ($setprivs) { + if ($env{'form.switchrole'} =~ m-^(in|ta|ep|ad|st|cr)([\w/]*)\./\Q$cdom\E/\Q$cnum\E(/?\w*)$-) { + my $role = $1; + my $custom_role = $2; + my $usec = $3; + if ($role eq 'cr') { + if ($custom_role =~ m-^$match_domain/$match_courseid/\w+$-) { + $role .= $custom_role; + } else { + return; + } + } + my (%userroles,%newrole,%newgroups); + my $area = '/'.$cdom.'/'.$cnum; + my $spec = $role.'.'.$area; + if ($usec ne '') { + $spec .= '/'.$usec; + $area .= '/'.$usec; + } + &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum,$area); + &Apache::lonnet::set_userprivs(\%userroles,\%newrole,%newgroups); + my $adhocstart = $then-1; + $userroles{'user.role.'.$spec} = $adhocstart.'.'; + &Apache::lonnet::appenv(\%userroles,[$role,'cm']); + } + } + } + return; +} + +sub check_forcc { + my ($cdom,$cnum,$then) = @_; + my $is_cc; + if ($cdom ne '' && $cnum ne '') { + if (&Apache::lonnet::is_course($cdom,$cnum)) { + my $envkey = 'user.role.cc./'.$cdom.'/'.$cnum; + if (defined($env{$envkey})) { + $is_cc = 1; + my ($tstart,$tend)=split(/\./,$env{$envkey}); + if ($tstart && $tstart>$then) { $is_cc = 0; } + if ($tend && $tend <$then) { $is_cc = 0; } + } + } + } + return $is_cc; +} + sub courselink { - my ($dcdom,$rowtype,$selecttype) = @_; + my ($dcdom,$rowtype) = @_; my $courseform=&Apache::loncommon::selectcourse_link ('rolechoice','dccourse'.$rowtype.'_'.$dcdom, 'dcdomain'.$rowtype.'_'.$dcdom,'coursedesc'.$rowtype.'_'. @@ -954,6 +1136,10 @@ sub courselink { } sub coursepick_jscript { + my %lt = &Apache::lonlocal::texthash( + plsu => "Please use the 'Select Course' link to open a separate pick course window where you may select the course you wish to enter.", + youc => 'You can only use this screen to select courses in the current domain.', + ); my $verify_script = <<"END";
 '.&mt('User Role').''.&mt('Extent') + .''.&mt('Start').''.&mt('End') + .'
". + &mt($type)."