![]() ![]() | ![]() |
- lots of \w -> probper regexp replacements
1: # The LearningOnline Network with CAPA 2: # User Roles Screen 3: # 4: # $Id: lonroles.pm,v 1.172 2006/12/05 02:55:56 albertel Exp $ 5: # 6: # Copyright Michigan State University Board of Trustees 7: # 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA). 9: # 10: # LON-CAPA is free software; you can redistribute it and/or modify 11: # it under the terms of the GNU General Public License as published by 12: # the Free Software Foundation; either version 2 of the License, or 13: # (at your option) any later version. 14: # 15: # LON-CAPA is distributed in the hope that it will be useful, 16: # but WITHOUT ANY WARRANTY; without even the implied warranty of 17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18: # GNU General Public License for more details. 19: # 20: # You should have received a copy of the GNU General Public License 21: # along with LON-CAPA; if not, write to the Free Software 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23: # 24: # /home/httpd/html/adm/gpl.txt 25: # 26: # http://www.lon-capa.org/ 27: # 28: ### 29: 30: package Apache::lonroles; 31: 32: use strict; 33: use Apache::lonnet; 34: use Apache::lonuserstate(); 35: use Apache::Constants qw(:common); 36: use Apache::File(); 37: use Apache::lonmenu; 38: use Apache::loncommon; 39: use Apache::lonhtmlcommon; 40: use Apache::lonannounce; 41: use Apache::lonlocal; 42: use Apache::lonpageflip(); 43: use Apache::lonnavdisplay(); 44: use GDBM_File; 45: use LONCAPA qw(:DEFAULT :match); 46: 47: 48: sub redirect_user { 49: my ($r,$title,$url,$msg,$launch_nav) = @_; 50: $msg = $title if (! defined($msg)); 51: &Apache::loncommon::content_type($r,'text/html'); 52: &Apache::loncommon::no_cache($r); 53: $r->send_http_header; 54: my $swinfo=&Apache::lonmenu::rawconfig(); 55: my $navwindow; 56: if ($launch_nav eq 'on') { 57: $navwindow.=&Apache::lonnavdisplay::launch_win('now',undef,undef, 58: ($url =~ m-^/adm/whatsnew-)); 59: } else { 60: $navwindow.=&Apache::lonnavmaps::close(); 61: } 62: my $start_page = &Apache::loncommon::start_page('Switching Role',undef, 63: {'redirect' => [1,$url],}); 64: my $end_page = &Apache::loncommon::end_page(); 65: 66: # Note to style police: 67: # This must only replace the spaces, nothing else, or it bombs elsewhere. 68: $url=~s/ /\%20/g; 69: $r->print(<<ENDREDIR); 70: $start_page 71: <script type="text/javascript"> 72: $swinfo 73: </script> 74: $navwindow 75: <h1>$msg</h1> 76: $end_page 77: ENDREDIR 78: return; 79: } 80: 81: sub error_page { 82: my ($r,$error,$dest)=@_; 83: &Apache::loncommon::content_type($r,'text/html'); 84: &Apache::loncommon::no_cache($r); 85: $r->send_http_header; 86: return OK if $r->header_only; 87: $r->print(&Apache::loncommon::start_page('Problems during Course Initialization'). 88: '<script type="text/javascript">'. 89: &Apache::lonmenu::rawconfig().'</script>'. 90: '<p>'.&mt('The following problems occurred:'). 91: $error. 92: '</p><br /><a href="'.$dest.'">'.&mt('Continue').'</a>'. 93: &Apache::loncommon::end_page()); 94: } 95: 96: sub handler { 97: 98: my $r = shift; 99: 100: my $now=time; 101: my $then=$env{'user.login.time'}; 102: my $envkey; 103: my %dcroles = (); 104: my $numdc = &check_fordc(\%dcroles,$then); 105: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); 106: 107: # ================================================================== Roles Init 108: if ($env{'form.selectrole'}) { 109: if ($env{'form.newrole'}) { 110: $env{'form.'.$env{'form.newrole'}}=1; 111: } 112: if ($env{'request.course.id'}) { 113: my %temp=('logout_'.$env{'request.course.id'} => time); 114: &Apache::lonnet::put('email_status',\%temp); 115: &Apache::lonnet::delenv('user.state.'.$env{'request.course.id'}); 116: } 117: &Apache::lonnet::appenv("request.course.id" => '', 118: "request.course.fn" => '', 119: "request.course.uri" => '', 120: "request.course.sec" => '', 121: "request.role" => 'cm', 122: "request.role.adv" => $env{'user.adv'}, 123: "request.role.domain" => $env{'user.domain'}); 124: 125: # Check if user is a DC trying to enter a course and needs privs to be created 126: if ($numdc > 0) { 127: foreach my $envkey (keys %env) { 128: if (my ($domain,$coursenum) = 129: ($envkey =~ m-^form\.cc\./($match_domain)/($match_courseid)$-)) { 130: if ($dcroles{$domain}) { 131: &check_privs($domain,$coursenum,$then,$now); 132: } 133: last; 134: } 135: } 136: } 137: 138: foreach $envkey (keys %env) { 139: next if ($envkey!~/^user\.role\./); 140: my ($where,$trolecode,$role,$tstatus,$tend,$tstart); 141: &role_status($envkey,$then,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend); 142: if ($env{'form.'.$trolecode}) { 143: if ($tstatus eq 'is') { 144: $where=~s/^\///; 145: my ($cdom,$cnum,$csec)=split(/\//,$where); 146: # check for course groups 147: my %coursegroups = &Apache::lonnet::get_active_groups( 148: $env{'user.domain'},$env{'user.name'},$cdom, $cnum); 149: my $cgrps = join(':',keys(%coursegroups)); 150: 151: # store role if recent_role list being kept 152: if ($env{'environment.recentroles'}) { 153: my %frozen_roles = 154: &Apache::lonhtmlcommon::get_recent_frozen('roles',$env{'environment.recentrolesn'}); 155: &Apache::lonhtmlcommon::store_recent('roles', 156: $trolecode,' ',$frozen_roles{$trolecode}); 157: } 158: 159: 160: # check for keyed access 161: if (($role eq 'st') && 162: ($env{'course.'.$cdom.'_'.$cnum.'.keyaccess'} eq 'yes')) { 163: # who is key authority? 164: my $authdom=$cdom; 165: my $authnum=$cnum; 166: if ($env{'course.'.$cdom.'_'.$cnum.'.keyauth'}) { 167: ($authnum,$authdom)= 168: split(/:/,$env{'course.'.$cdom.'_'.$cnum.'.keyauth'}); 169: } 170: # check with key authority 171: unless (&Apache::lonnet::validate_access_key( 172: $env{'environment.key.'.$cdom.'_'.$cnum}, 173: $authdom,$authnum)) { 174: # there is no valid key 175: if ($env{'form.newkey'}) { 176: # student attempts to register a new key 177: &Apache::loncommon::content_type($r,'text/html'); 178: &Apache::loncommon::no_cache($r); 179: $r->send_http_header; 180: my $swinfo=&Apache::lonmenu::rawconfig(); 181: my $start_page=&Apache::loncommon::start_page 182: ('Verifying Access Key to Unlock this Course'); 183: my $end_page=&Apache::loncommon::end_page(); 184: my $buttontext=&mt('Enter Course'); 185: my $message=&mt('Successfully registered key'); 186: my $assignresult= 187: &Apache::lonnet::assign_access_key( 188: $env{'form.newkey'}, 189: $authdom,$authnum, 190: $cdom,$cnum, 191: $env{'user.domain'}, 192: $env{'user.name'}, 193: 'Assigned from '.$ENV{'REMOTE_ADDR'}.' at '.localtime().' for '. 194: $trolecode); 195: unless ($assignresult eq 'ok') { 196: $assignresult=~s/^error\:\s*//; 197: $message=&mt($assignresult). 198: '<br /><a href="/adm/logout">'. 199: &mt('Logout').'</a>'; 200: $buttontext=&mt('Re-Enter Key'); 201: } 202: $r->print(<<ENDENTEREDKEY); 203: $start_page 204: <script> 205: $swinfo 206: </script> 207: <form method="post"> 208: <input type="hidden" name="selectrole" value="1" /> 209: <input type="hidden" name="$trolecode" value="1" /> 210: <font size="+2">$message</font><br /> 211: <input type="submit" value="$buttontext" /> 212: </form> 213: $end_page 214: ENDENTEREDKEY 215: return OK; 216: } else { 217: # print form to enter a new key 218: &Apache::loncommon::content_type($r,'text/html'); 219: &Apache::loncommon::no_cache($r); 220: $r->send_http_header; 221: my $swinfo=&Apache::lonmenu::rawconfig(); 222: my $start_page=&Apache::loncommon::start_page 223: ('Enter Access Key to Unlock this Course'); 224: my $end_page=&Apache::loncommon::end_page(); 225: $r->print(<<ENDENTERKEY); 226: $start_page 227: <script> 228: $swinfo 229: </script> 230: <form method="post"> 231: <input type="hidden" name="selectrole" value="1" /> 232: <input type="hidden" name="$trolecode" value="1" /> 233: <input type="text" size="20" name="newkey" value="$env{'form.newkey'}" /> 234: <input type="submit" value="Enter key" /> 235: </form> 236: $end_page 237: ENDENTERKEY 238: return OK; 239: } 240: } 241: } 242: &Apache::lonnet::log($env{'user.domain'}, 243: $env{'user.name'}, 244: $env{'user.home'}, 245: "Role ".$trolecode); 246: 247: &Apache::lonnet::appenv( 248: 'request.role' => $trolecode, 249: 'request.role.domain' => $cdom, 250: 'request.course.sec' => $csec, 251: 'request.course.groups' => $cgrps); 252: my $tadv=0; 253: 254: if (($cnum) && ($role ne 'ca') && ($role ne 'aa')) { 255: my $msg; 256: my ($furl,$ferr)= 257: &Apache::lonuserstate::readmap($cdom.'/'.$cnum); 258: if (($env{'form.orgurl'}) && 259: ($env{'form.orgurl'}!~/^\/adm\/flip/)) { 260: my $dest=$env{'form.orgurl'}; 261: if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; } 262: &Apache::lonnet::appenv('request.role.adv'=>$tadv); 263: if (($ferr) && ($tadv)) { 264: &error_page($r,$ferr,$dest); 265: } else { 266: $r->internal_redirect($dest); 267: } 268: return OK; 269: } else { 270: if (!$env{'request.course.id'}) { 271: &Apache::lonnet::appenv( 272: "request.course.id" => $cdom.'_'.$cnum); 273: $furl='/adm/roles?tryagain=1'; 274: $msg= 275: '<h1><span class="LC_error">'. 276: &mt('Could not initialize [_1] at this time.', 277: $env{'course.'.$cdom.'_'.$cnum.'.description'}). 278: '</span></h1><h3>'.&mt('Please try again.').'</h3>'.$ferr; 279: } 280: if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; } 281: &Apache::lonnet::appenv('request.role.adv'=>$tadv); 282: 283: if (($ferr) && ($tadv)) { 284: &error_page($r,$ferr,$furl); 285: } else { 286: # Check to see if the user is a CC entering a course 287: # for the first time 288: my (undef, undef, $role, $courseid) = split(/\./, $envkey); 289: if (substr($courseid, 0, 1) eq '/') { 290: $courseid = substr($courseid, 1); 291: } 292: $courseid =~ s/\//_/; 293: if ($role eq 'cc' && $env{'course.' . $courseid . 294: '.course.helper.not.run'}) { 295: $furl = "/adm/helper/course.initialization.helper"; 296: # Send the user to the course they selected 297: } elsif ($env{'request.course.id'}) { 298: if (&Apache::lonnet::allowed('whn', 299: $env{'request.course.id'}) 300: || &Apache::lonnet::allowed('whn', 301: $env{'request.course.id'}.'/' 302: .$env{'request.course.sec'}) 303: ) { 304: my $startpage = &courseloadpage($courseid); 305: unless ($startpage eq 'firstres') { 306: $msg = &mt('Entering [_1] ....', 307: $env{'course.'.$courseid.'.description'}); 308: &redirect_user($r,&mt('New in course'), 309: '/adm/whatsnew?refpage=start',$msg, 310: $env{'environment.remotenavmap'}); 311: return OK; 312: } 313: } 314: } 315: # Are we allowed to look at the first resource? 316: if ($furl !~ m|^/adm/|) { 317: # Guess not ... 318: $furl=&Apache::lonpageflip::first_accessible_resource(); 319: } 320: $msg = &mt('Entering [_1] ...', 321: $env{'course.'.$courseid.'.description'}); 322: &redirect_user($r,&mt('Entering [_1]', 323: $env{'course.'.$courseid.'.description'}), 324: $furl,$msg, 325: $env{'environment.remotenavmap'}); 326: } 327: return OK; 328: } 329: } 330: # 331: # Send the user to the construction space they selected 332: if ($role =~ /^(au|ca|aa)$/) { 333: my $redirect_url = '/priv/'; 334: if ($role eq 'au') { 335: $redirect_url.=$env{'user.name'}; 336: } else { 337: $where =~ /\/(.*)$/; 338: $redirect_url .= $1; 339: } 340: $redirect_url .= '/'; 341: &redirect_user($r,&mt('Entering Construction Space'), 342: $redirect_url); 343: return OK; 344: } 345: if ($role eq 'dc') { 346: my $redirect_url = '/adm/menu/'; 347: &redirect_user($r,&mt('Loading Domain Coordinator Menu'), 348: $redirect_url); 349: return OK; 350: } 351: } 352: } 353: } 354: } 355: 356: 357: # =============================================================== No Roles Init 358: 359: &Apache::loncommon::content_type($r,'text/html'); 360: &Apache::loncommon::no_cache($r); 361: $r->send_http_header; 362: return OK if $r->header_only; 363: 364: my $swinfo=&Apache::lonmenu::rawconfig(); 365: my $start_page=&Apache::loncommon::start_page('User Roles'); 366: my $standby=&mt('Role selected. Please stand by.'); 367: $standby=~s/\n/\\n/g; 368: 369: $r->print(<<ENDHEADER); 370: $start_page 371: <br /> 372: <script> 373: $swinfo 374: window.focus(); 375: 376: active=true; 377: 378: function enterrole (thisform,rolecode,buttonname) { 379: if (active) { 380: active=false; 381: document.title='$standby'; 382: window.status='$standby'; 383: thisform.newrole.value=rolecode; 384: thisform.submit(); 385: } else { 386: alert('$standby'); 387: } 388: } 389: </script> 390: ENDHEADER 391: 392: # ------------------------------------------ Get Error Message from Environment 393: 394: my ($fn,$priv,$nochoose,$error,$msg)=split(/:/,$env{'user.error.msg'}); 395: if ($env{'user.error.msg'}) { 396: $r->log_reason( 397: "$msg for $env{'user.name'} domain $env{'user.domain'} access $priv",$fn); 398: } 399: 400: # ------------------------------------------------- Can this user re-init, etc? 401: 402: my $advanced=$env{'user.adv'}; 403: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['tryagain']); 404: my $tryagain=$env{'form.tryagain'}; 405: 406: # -------------------------------------------------------- Generate Page Output 407: # --------------------------------------------------------------- Error Header? 408: if ($error) { 409: $r->print("<h1>LON-CAPA Access Control</h1>"); 410: $r->print("<!-- LONCAPAACCESSCONTROLERRORSCREEN --><hr /><pre>Access : ". 411: Apache::lonnet::plaintext($priv)."\n"); 412: $r->print("Resource: ".&Apache::lonenc::check_encrypt($fn)."\n"); 413: $r->print("Action : $msg\n</pre><hr />"); 414: my $url=$fn; 415: my $last; 416: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', 417: &GDBM_READER(),0640)) { 418: $last=$hash{'last_known'}; 419: untie(%hash); 420: } 421: if ($last) { $fn.='?symb='.&escape($last); } 422: 423: &Apache::londocs::changewarning($r,undef,'You have modified your course recently, [_1] may fix this access problem.', 424: &Apache::lonenc::check_encrypt($fn)); 425: } else { 426: if ($env{'user.error.msg'}) { 427: $r->print( 428: '<h3><span class="LC_error">'. 429: &mt('You need to choose another user role or enter a specific course for this function').'</span></h3>'); 430: } 431: } 432: # -------------------------------------------------------- Choice or no choice? 433: if ($nochoose) { 434: $r->print("<h2>".&mt('Sorry ...')."</h2>\n". 435: &mt('This action is currently not authorized.'). 436: &Apache::loncommon::end_page()); 437: return OK; 438: } else { 439: if ($advanced) { 440: $r->print(&mt("Your home server is "). 441: $Apache::lonnet::hostname{&Apache::lonnet::homeserver 442: ($env{'user.name'},$env{'user.domain'})}. 443: "<br />\n"); 444: $r->print(&mt( 445: "Author and Co-Author roles are not available on servers other than their respective home servers.")); 446: } 447: if (($ENV{'REDIRECT_QUERY_STRING'}) && ($fn)) { 448: $fn.='?'.$ENV{'REDIRECT_QUERY_STRING'}; 449: } 450: $r->print('<form method="post" name="rolechoice" action="'.(($fn)?$fn:$r->uri).'">'); 451: $r->print('<input type="hidden" name="orgurl" value="'.$fn.'" />'); 452: $r->print('<input type="hidden" name="selectrole" value="1" />'); 453: $r->print('<input type="hidden" name="newrole" value="" />'); 454: } 455: if ($env{'user.adv'}) { 456: $r->print( 457: '<br /><label>'.&mt('Show all roles').': <input type="checkbox" name="showall"'); 458: if ($env{'form.showall'}) { $r->print(' checked="checked" '); } 459: $r->print(' /></label><input type="submit" value="'.&mt('Display').'" />'); 460: } 461: 462: my (%roletext,%sortrole,%roleclass); 463: my $countactive=0; 464: my $inrole=0; 465: my $possiblerole=''; 466: foreach $envkey (sort keys %env) { 467: my $button = 1; 468: my $switchserver=''; 469: my $roletext; 470: my $sortkey; 471: if ($envkey=~/^user\.role\./) { 472: my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend,$tfont); 473: &role_status($envkey,$then,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend); 474: next if (!defined($role) || $role eq '' || $role =~ /^gr/); 475: $tremark=''; 476: $tpstart=' '; 477: $tpend=' '; 478: $tfont='#000000'; 479: if ($tstart) { 480: $tpstart=&Apache::lonlocal::locallocaltime($tstart); 481: } 482: if ($tend) { 483: $tpend=&Apache::lonlocal::locallocaltime($tend); 484: } 485: if ($env{'request.role'} eq $trolecode) { 486: $tstatus='selected'; 487: } 488: my $tbg; 489: if (($tstatus eq 'is') 490: || ($tstatus eq 'selected') 491: || ($tstatus eq 'will') 492: || ($tstatus eq 'future') 493: || ($env{'form.showall'})) { 494: if ($tstatus eq 'is') { 495: $tbg='#77FF77'; 496: $tfont='#003300'; 497: $possiblerole=$trolecode; 498: $countactive++; 499: } elsif ($tstatus eq 'future') { 500: $tbg='#FFFF77'; 501: $button=0; 502: } elsif ($tstatus eq 'will') { 503: $tbg='#FFAA77'; 504: $tremark.=&mt('Active at next login. '); 505: } elsif ($tstatus eq 'expired') { 506: $tbg='#FF7777'; 507: $tfont='#330000'; 508: $button=0; 509: } elsif ($tstatus eq 'will_not') { 510: $tbg='#AAFF77'; 511: $tremark.=&mt('Expired after logout. '); 512: } elsif ($tstatus eq 'selected') { 513: $tbg='#11CC55'; 514: $tfont='#002200'; 515: $inrole=1; 516: $countactive++; 517: $tremark.=&mt('Currently selected. '); 518: } 519: my $trole; 520: if ($role =~ /^cr\//) { 521: my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$role); 522: if ($tremark) { $tremark.='<br />'; } 523: $tremark.=&mt('Defined by ').$rauthor. 524: &mt(' at ').$rdomain.'.'; 525: } 526: $trole=Apache::lonnet::plaintext($role); 527: my $ttype; 528: my $twhere; 529: my ($tdom,$trest,$tsection)= 530: split(/\//,Apache::lonnet::declutter($where)); 531: # First, Co-Authorship roles 532: if (($role eq 'ca') || ($role eq 'aa')) { 533: my $home = &Apache::lonnet::homeserver($trest,$tdom); 534: my $allowed=0; 535: my @ids=&Apache::lonnet::current_machine_ids(); 536: foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } 537: if (!$allowed) { 538: $button=0; 539: $switchserver='otherserver='.$home.'&role='.$trolecode; 540: } 541: #next if ($home eq 'no_host'); 542: $home = $Apache::lonnet::hostname{$home}; 543: $ttype='Construction Space'; 544: $twhere=&mt('User').': '.$trest.'<br />'.&mt('Domain'). 545: ': '.$tdom.'<br />'. 546: ' '.&mt('Server').': '.$home; 547: $env{'course.'.$tdom.'_'.$trest.'.description'}='ca'; 548: $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$trest.'/'); 549: $sortkey=$role."$trest:$tdom"; 550: } elsif ($role eq 'au') { 551: # Authors 552: my $home = &Apache::lonnet::homeserver 553: ($env{'user.name'},$env{'user.domain'}); 554: my $allowed=0; 555: my @ids=&Apache::lonnet::current_machine_ids(); 556: foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } 557: if (!$allowed) { 558: $button=0; 559: $switchserver='otherserver='.$home.'&role='.$trolecode; 560: } 561: #next if ($home eq 'no_host'); 562: $home = $Apache::lonnet::hostname{$home}; 563: $ttype='Construction Space'; 564: $twhere=&mt('Domain').': '.$tdom.'<br />'.&mt('Server'). 565: ': '.$home; 566: $env{'course.'.$tdom.'_'.$trest.'.description'}='ca'; 567: $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$env{'user.name'}.'/'); 568: $sortkey=$role; 569: } elsif ($trest) { 570: my $tcourseid=$tdom.'_'.$trest; 571: $ttype = &Apache::loncommon::course_type($tcourseid); 572: $trole = &Apache::lonnet::plaintext($role,$ttype); 573: if ($env{'course.'.$tcourseid.'.description'}) { 574: $twhere=$env{'course.'.$tcourseid.'.description'}; 575: $sortkey=$role."\0".$tdom."\0".$twhere."\0".$envkey; 576: unless ($twhere eq &mt('Currently not available')) { 577: $twhere.=' <font size="-2">'. 578: &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom,$tfont). 579: '</font>'; 580: } 581: } else { 582: my %newhash=&Apache::lonnet::coursedescription($tcourseid); 583: if (%newhash) { 584: $sortkey=$role."\0".$tdom."\0".$newhash{'description'}. 585: "\0".$envkey; 586: $twhere=$newhash{'description'}. 587: ' <font size="-2">'. 588: &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom,$tfont). 589: '</font>'; 590: $ttype = $newhash{'type'}; 591: $trole = &Apache::lonnet::plaintext($role,$ttype); 592: } else { 593: $twhere=&mt('Currently not available'); 594: $env{'course.'.$tcourseid.'.description'}=$twhere; 595: $sortkey=$role."\0".$tdom."\0".$twhere."\0".$envkey; 596: $ttype = 'Unavailable'; 597: } 598: } 599: if ($tsection) { 600: $twhere.='<br />'.&mt('Section/Group').': '.$tsection; 601: } 602: if ($role ne 'st') { $twhere.="<br />".&mt('Domain').":".$tdom; } 603: } elsif ($tdom) { 604: $ttype='Domain'; 605: $twhere=$tdom; 606: $sortkey=$role.$twhere; 607: } else { 608: $ttype='System'; 609: $twhere=&mt('system wide'); 610: $sortkey=$role.$twhere; 611: } 612: $roletext.=&build_roletext($trolecode,$tdom,$trest,$tstatus,$tryagain,$advanced,$tremark,$tbg,$tfont,$trole,$twhere,$tpstart,$tpend,$nochoose,$button,$switchserver); 613: $roletext{$envkey}=$roletext; 614: if (!$sortkey) {$sortkey=$twhere."\0".$envkey;} 615: $sortrole{$sortkey}=$envkey; 616: $roleclass{$envkey}=$ttype; 617: } 618: } 619: } 620: # No active roles 621: if ($countactive==0) { 622: if ($inrole) { 623: $r->print('<h2>'.&mt('Currently no additional roles or courses').'</h2>'); 624: } else { 625: $r->print('<h2>'.&mt('Currently no active roles or courses').'</h2>'); 626: } 627: $r->print('</form>'.&Apache::loncommon::end_page()); 628: return OK; 629: # Is there only one choice? 630: } elsif (($countactive==1) && ($env{'request.role'} eq 'cm')) { 631: $r->print('<h3>'.&mt('Please stand by.').'</h3>'. 632: '<input type="hidden" name="'.$possiblerole.'" value="1" />'); 633: $r->print("</form>\n"); 634: $r->rflush(); 635: $r->print('<script>document.forms.rolechoice.submit();</script>'); 636: $r->print(&Apache::loncommon::end_page()); 637: return OK; 638: } 639: # More than one possible role 640: # ----------------------------------------------------------------------- Table 641: unless (($advanced) || ($nochoose)) { 642: $r->print("<h2>".&mt('Select a Course/Group to Enter')."</h2>\n"); 643: } 644: $r->print('<br /><table><tr>'); 645: unless ($nochoose) { $r->print('<th> </th>'); } 646: $r->print('<th>'.&mt('User Role').'</th><th>'.&mt('Extent'). 647: '</th><th>'.&mt('Start').'</th><th>'.&mt('End').'</th></tr>'."\n"); 648: my $doheaders=-1; 649: foreach my $type ('Domain','Construction Space','Course','Group','Unavailable','System') { 650: my $haverole=0; 651: foreach my $which (sort {uc($a) cmp uc($b)} (keys(%sortrole))) { 652: if ($roleclass{$sortrole{$which}} =~ /^\Q$type\E/) { 653: $haverole=1; 654: } 655: } 656: if ($haverole) { $doheaders++; } 657: } 658: 659: if ($env{'environment.recentroles'}) { 660: my %recent_roles = 661: &Apache::lonhtmlcommon::get_recent('roles',$env{'environment.recentrolesn'}); 662: my $output=''; 663: foreach (sort(keys(%recent_roles))) { 664: if (defined($roletext{'user.role.'.$_})) { 665: $output.=$roletext{'user.role.'.$_}; 666: if ($_ =~ m-dc\./($match_domain)/- 667: && $dcroles{$1}) { 668: $output .= &allcourses_row($1,'recent'); 669: } 670: } elsif ($numdc > 0) { 671: unless ($_ =~/^error\:/) { 672: $output.=&display_cc_role('user.role.'.$_); 673: } 674: } 675: } 676: if ($output) { 677: $r->print("<tr><td align='center' colspan='5'><font face='arial'>". 678: &mt('Recent Roles')."</font></td>"); 679: $r->print($output); 680: $r->print("</tr>"); 681: $doheaders ++; 682: } 683: } 684: 685: if ($numdc > 0) { 686: $r->print(&coursepick_jscript()); 687: $r->print(&Apache::loncommon::coursebrowser_javascript()); 688: } 689: foreach my $type ('Construction Space','Domain','Course','Group','Unavailable','System') { 690: my $output; 691: foreach my $which (sort {uc($a) cmp uc($b)} (keys(%sortrole))) { 692: if ($roleclass{$sortrole{$which}} =~ /^\Q$type\E/) { 693: $output.=$roletext{$sortrole{$which}}; 694: if ($sortrole{$which} =~ m-dc\./($match_domain)/-) { 695: if ($dcroles{$1}) { 696: $output .= &allcourses_row($1,''); 697: } 698: } 699: } 700: } 701: if ($output) { 702: if ($doheaders > 0) { 703: $r->print("<tr>". 704: "<td align='center' colspan='5'><font face='arial'>".&mt($type)."</font></td></tr>"); 705: } 706: $r->print($output); 707: } 708: } 709: my $tremark=''; 710: my $tfont='#003300'; 711: if ($env{'request.role'} eq 'cm') { 712: $r->print('<tr bgcolor="#11CC55">'); 713: $tremark=&mt('Currently selected. '); 714: $tfont='#002200'; 715: } else { 716: $r->print('<tr bgcolor="#77FF77">'); 717: } 718: unless ($nochoose) { 719: if ($env{'request.role'} ne 'cm') { 720: $r->print('<td><input type="submit" value="'. 721: &mt('Select').'" name="cm"></td>'); 722: } else { 723: $r->print('<td> </td>'); 724: } 725: } 726: $r->print('<td colspan="3"><font color="'.$tfont.'">'.&mt('No role specified'). 727: '</font></td><td><font color="'.$tfont.'">'.$tremark. 728: ' </font></td></tr>'."\n"); 729: 730: $r->print('</table>'); 731: unless ($nochoose) { 732: $r->print("</form>\n"); 733: } 734: # ------------------------------------------------------------ Privileges Info 735: if (($advanced) && (($env{'user.error.msg'}) || ($error))) { 736: $r->print('<hr /><h2>Current Privileges</h2>'); 737: 738: foreach $envkey (sort keys %env) { 739: if ($envkey=~/^user\.priv\.$env{'request.role'}\./) { 740: my $where=$envkey; 741: $where=~s/^user\.priv\.$env{'request.role'}\.//; 742: my $ttype; 743: my $twhere; 744: my ($tdom,$trest,$tsec)= 745: split(/\//,Apache::lonnet::declutter($where)); 746: if ($trest) { 747: if ($env{'course.'.$tdom.'_'.$trest.'.description'} eq 'ca') { 748: $ttype='Construction Space'; 749: $twhere='User: '.$trest.', Domain: '.$tdom; 750: } else { 751: $ttype= 752: &Apache::loncommon::course_type($tdom.'_'.$trest); 753: $twhere=$env{'course.'.$tdom.'_'.$trest.'.description'}; 754: if ($tsec) { 755: $twhere.=' (Section: '.$tsec.')'; 756: } 757: } 758: } elsif ($tdom) { 759: $ttype='Domain'; 760: $twhere=$tdom; 761: } else { 762: $ttype='System'; 763: $twhere='/'; 764: } 765: $r->print("\n<h3>".$ttype.': '.$twhere.'</h3><ul>'); 766: foreach (sort split(/:/,$env{$envkey})) { 767: if ($_) { 768: my ($prv,$restr)=split(/\&/,$_); 769: my $trestr=''; 770: if ($restr ne 'F') { 771: my $i; 772: $trestr.=' ('; 773: for ($i=0;$i<length($restr);$i++) { 774: $trestr.= 775: Apache::lonnet::plaintext(substr($restr,$i,1)); 776: if ($i<length($restr)-1) { $trestr.=', '; } 777: } 778: $trestr.=')'; 779: } 780: $r->print('<li>'. 781: Apache::lonnet::plaintext($prv).$trestr. 782: '</li>'); 783: } 784: } 785: $r->print('</ul>'); 786: } 787: } 788: } 789: $r->print(&Apache::lonnet::getannounce()); 790: if ($advanced) { 791: $r->print('<p><small><i>This is LON-CAPA '. 792: $r->dir_config('lonVersion').'</i><br />'. 793: '<a href="/adm/logout">'.&mt('Logout').'</a></small></p>'); 794: } 795: $r->print(&Apache::loncommon::end_page()); 796: return OK; 797: } 798: 799: sub role_status { 800: my ($rolekey,$then,$now,$role,$where,$trolecode,$tstatus,$tstart,$tend) = @_; 801: my @pwhere = (); 802: if (exists($env{$rolekey}) && $env{$rolekey} ne '') { 803: (undef,undef,$$role,@pwhere)=split(/\./,$rolekey); 804: unless (!defined($$role) || $$role eq '') { 805: $$where=join('.',@pwhere); 806: $$trolecode=$$role.'.'.$$where; 807: ($$tstart,$$tend)=split(/\./,$env{$rolekey}); 808: $$tstatus='is'; 809: if ($$tstart && $$tstart>$then) { 810: $$tstatus='future'; 811: if ($$tstart<$now) { $$tstatus='will'; } 812: } 813: if ($$tend) { 814: if ($$tend<$then) { 815: $$tstatus='expired'; 816: } elsif ($$tend<$now) { 817: $$tstatus='will_not'; 818: } 819: } 820: } 821: } 822: } 823: 824: sub build_roletext { 825: my ($trolecode,$tdom,$trest,$tstatus,$tryagain,$advanced,$tremark,$tbg,$tfont,$trole,$twhere,$tpstart,$tpend,$nochoose,$button,$switchserver) = @_; 826: my $roletext='<tr bgcolor="'.$tbg.'">'; 827: my $is_dc=($trolecode =~ m/^dc\./); 828: my $rowspan=($is_dc) ? '' 829: : ' rowspan="2" '; 830: 831: unless ($nochoose) { 832: my $buttonname=$trolecode; 833: $buttonname=~s/\W//g; 834: if (!$button) { 835: if ($switchserver) { 836: $roletext.='<td'.$rowspan.'><a href="/adm/switchserver?'. 837: $switchserver.'">'.&mt('Switch Server').'</a></td>'; 838: } else { 839: $roletext.=('<td'.$rowspan.'> </td>'); 840: } 841: } elsif ($tstatus eq 'is') { 842: $roletext.='<td'.$rowspan.'><input name="'.$buttonname.'" type="button" value="'. 843: &mt('Select').'" onClick="javascript:enterrole(this.form,\''. 844: $trolecode."','".$buttonname.'\');"></td>'; 845: } elsif ($tryagain) { 846: $roletext.= 847: '<td'.$rowspan.'><input name="'.$buttonname.'" type="button" value="'. 848: &mt('Try Selecting Again').'" onClick="javascript:enterrole(this.form,\''. 849: $trolecode."','".$buttonname.'\');"></td>'; 850: } elsif ($advanced) { 851: $roletext.= 852: '<td'.$rowspan.'><input name="'.$buttonname.'" type="button" value="'. 853: &mt('Re-Initialize').'" onClick="javascript:enterrole(this.form,\''. 854: $trolecode."','".$buttonname.'\');"></td>'; 855: } else { 856: $roletext.='<td'.$rowspan.'> </td>'; 857: } 858: } 859: if ($trolecode !~ m/^(dc|ca|au|aa)\./) { 860: $tremark.=&Apache::lonannounce::showday(time,1, 861: &Apache::lonannounce::readcalendar($tdom.'_'.$trest)); 862: } 863: $roletext.='<td><font color="'.$tfont.'">'.$trole. 864: '</font></td><td><font color="'.$tfont.'">'.$twhere. 865: '</font></td><td><font color="'.$tfont.'">'.$tpstart. 866: '</font></td><td><font color="'.$tfont.'">'.$tpend. 867: '</font></td></tr>'; 868: if (!$is_dc) { 869: $roletext.='<tr bgcolor="'.$tbg.'"><td colspan="4"><font color="'.$tfont.'">'.$tremark. 870: ' </font></td></tr><tr><td colspan="5" height="3"></td></tr>'."\n"; 871: } 872: return $roletext; 873: } 874: 875: sub check_privs { 876: my ($cdom,$cnum,$then,$now) = @_; 877: my $cckey = 'user.role.cc./'.$cdom.'/'.$cnum; 878: if ($env{$cckey}) { 879: my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend,$tfont); 880: &role_status($cckey,$then,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend); 881: unless (($tstatus eq 'is') || ($tstatus eq 'will_not')) { 882: &set_privileges($cdom,$cnum); 883: } 884: } else { 885: &set_privileges($cdom,$cnum); 886: } 887: } 888: 889: sub check_fordc { 890: my ($dcroles,$then) = @_; 891: my $numdc = 0; 892: if ($env{'user.adv'}) { 893: foreach my $envkey (sort keys %env) { 894: if ($envkey=~/^user\.role\.dc\.\/($match_domain)\/$/) { 895: my $dcdom = $1; 896: my $livedc = 1; 897: my ($tstart,$tend)=split(/\./,$env{$envkey}); 898: if ($tstart && $tstart>$then) { $livedc = 0; } 899: if ($tend && $tend <$then) { $livedc = 0; } 900: if ($livedc) { 901: $$dcroles{$dcdom} = $envkey; 902: $numdc++; 903: } 904: } 905: } 906: } 907: return $numdc; 908: } 909: 910: sub courselink { 911: my ($dcdom,$rowtype,$selecttype) = @_; 912: my $courseform=&Apache::loncommon::selectcourse_link 913: ('rolechoice','dccourse'.$rowtype.'_'.$dcdom, 914: 'dcdomain'.$rowtype.'_'.$dcdom,'coursedesc'.$rowtype.'_'. 915: $dcdom,$dcdom,undef,$selecttype); 916: my $hiddenitems = '<input type="hidden" name="dcdomain'.$rowtype.'_'.$dcdom.'" value="'.$dcdom.'" />'. 917: '<input type="hidden" name="origdom'.$rowtype.'_'.$dcdom.'" value="'.$dcdom.'" />'. 918: '<input type="hidden" name="dccourse'.$rowtype.'_'.$dcdom.'" value="" />'. 919: '<input type="hidden" name="coursedesc'.$rowtype.'_'.$dcdom.'" value="" />'; 920: return $courseform.$hiddenitems; 921: } 922: 923: sub coursepick_jscript { 924: my $verify_script = <<"END"; 925: <script> 926: function verifyCoursePick(caller) { 927: var numbutton = getIndex(caller) 928: var pickedCourse = document.rolechoice.elements[numbutton+4].value 929: var pickedDomain = document.rolechoice.elements[numbutton+2].value 930: if (document.rolechoice.elements[numbutton+2].value == document.rolechoice.elements[numbutton+3].value) { 931: if (pickedCourse != '') { 932: if (numbutton != -1) { 933: var courseTarget = "cc./"+pickedDomain+"/"+pickedCourse 934: document.rolechoice.elements[numbutton+1].name = courseTarget 935: document.rolechoice.submit() 936: } 937: } 938: else { 939: alert("Please use the 'Select Course' link to open a separate pick course window where you may select the course you wish to enter."); 940: } 941: } 942: else { 943: alert("You can only use this screen to select courses in the current domain") 944: } 945: } 946: function getIndex(caller) { 947: for (var i=0;i<document.rolechoice.elements.length;i++) { 948: if (document.rolechoice.elements[i] == caller) { 949: return i; 950: } 951: } 952: return -1; 953: } 954: </script> 955: END 956: return $verify_script; 957: } 958: 959: sub processpick { 960: my $process_pick = <<"END"; 961: <script> 962: function process_pick(dom) { 963: var pickedCourse=opener.document.rolechoice.$env{'form.cnumelement'}.value; 964: var pickedDomain=opener.document.rolechoice.$env{'form.cdomelement'}.value; 965: var okDomain = 0; 966: 967: if (pickedDomain == dom) { 968: if (pickedCourse != '') { 969: var courseTarget = "cc./"+pickedDomain+"/"+pickedCourse 970: opener.document.title='Role selected. Please stand by.'; 971: opener.status='Role selected. Please stand by.'; 972: opener.document.rolechoice.newrole.value=courseTarget 973: opener.document.rolechoice.submit() 974: } 975: } else { 976: alert("You may only use this screen to select courses in the current domain: "+dom+"\\nPlease return to the roles page window and click the 'Select Course' link for domain: "+pickedDomain+",\\n if you are a Domain Coordinator in that domain, and wish to become a Course Coordinator in a course in the domain"); 977: } 978: } 979: 980: </script> 981: END 982: return $process_pick; 983: } 984: 985: sub display_cc_role { 986: my $rolekey = shift; 987: my $roletext; 988: my $advanced = $env{'user.adv'}; 989: my $tryagain = $env{'form.tryagain'}; 990: unless ($rolekey =~/^error\:/) { 991: if ($rolekey =~ m-^user\.role.cc\./($match_domain)/($match_courseid)$-) { 992: my $tcourseid = $1.'_'.$2; 993: my $trolecode = 'cc./'.$1.'/'.$2; 994: my $twhere; 995: my $ttype; 996: my $tbg='#77FF77'; 997: my $tfont='#003300'; 998: my %newhash=&Apache::lonnet::coursedescription($tcourseid); 999: if (%newhash) { 1000: $twhere=$newhash{'description'}. 1001: ' <font size="-2">'. 1002: &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$2,$1,$tfont). 1003: '</font>'; 1004: $ttype = $newhash{'type'}; 1005: } else { 1006: $twhere=&mt('Currently not available'); 1007: $env{'course.'.$tcourseid.'.description'}=$twhere; 1008: } 1009: my $trole = &Apache::lonnet::plaintext('cc',$ttype); 1010: $twhere.="<br />".&mt('Domain').":".$1; 1011: $roletext = &build_roletext($trolecode,$1,$2,'is',$tryagain,$advanced,'',$tbg,$tfont,$trole,$twhere,'','','',1,''); 1012: } 1013: } 1014: return ($roletext); 1015: } 1016: 1017: sub allcourses_row { 1018: my ($dcdom,$rowtype) = @_; 1019: my $output = '<tr bgcolor="#77FF77">'. 1020: ' <td colspan="5">'; 1021: foreach my $type ('Course','Group') { 1022: my $selectlink = &courselink($dcdom,$rowtype,$type); 1023: my $ccrole = &Apache::lonnet::plaintext('cc',$type); 1024: $output.= '<font color="#002200">'.$ccrole.'</font>'. 1025: ' <b>'.$selectlink.'</b>'. 1026: ' from '.&mt('Domain').' '.$dcdom.'<br />'; 1027: } 1028: $output .= '</tr><tr><td colspan="5" height="3"></td></tr>'."\n"; 1029: return $output; 1030: } 1031: 1032: sub recent_filename { 1033: my $area=shift; 1034: return 'nohist_recent_'.&escape($area); 1035: } 1036: 1037: sub set_privileges { 1038: my ($dcdom,$pickedcourse) = @_; 1039: my $area = '/'.$dcdom.'/'.$pickedcourse; 1040: my $role = 'cc'; 1041: my $spec = $role.'.'.$area; 1042: my %userroles = &Apache::lonnet::set_arearole($role,$area,'','', 1043: $env{'user.domain'}, 1044: $env{'user.name'}); 1045: my %ccrole = (); 1046: &Apache::lonnet::standard_roleprivs(\%ccrole,$role,$dcdom,$spec,$pickedcourse,$area); 1047: my ($author,$adv)= &Apache::lonnet::set_userprivs(\%userroles,\%ccrole); 1048: &Apache::lonnet::appenv(%userroles); 1049: &Apache::lonnet::log($env{'user.domain'}, 1050: $env{'user.name'}, 1051: $env{'user.home'}, 1052: "Role ".$role); 1053: &Apache::lonnet::appenv( 1054: 'request.role' => $spec, 1055: 'request.role.domain' => $dcdom, 1056: 'request.course.sec' => ''); 1057: my $tadv=0; 1058: if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; } 1059: &Apache::lonnet::appenv('request.role.adv' => $tadv); 1060: } 1061: 1062: sub courseloadpage { 1063: my ($courseid) = @_; 1064: my $startpage; 1065: my %entry_settings = &Apache::lonnet::get('nohist_whatsnew', 1066: [$courseid.':courseinit']); 1067: my ($tmp) = %entry_settings; 1068: unless ($tmp =~ /^error: 2 /) { 1069: $startpage = $entry_settings{$courseid.':courseinit'}; 1070: } 1071: if ($startpage eq '') { 1072: if (exists($env{'environment.course_init_display'})) { 1073: $startpage = $env{'environment.course_init_display'}; 1074: } 1075: } 1076: return $startpage; 1077: } 1078: 1079: 1; 1080: __END__ 1081: 1082: =head1 NAME 1083: 1084: Apache::lonroles - User Roles Screen 1085: 1086: =head1 SYNOPSIS 1087: 1088: Invoked by /etc/httpd/conf/srm.conf: 1089: 1090: <Location /adm/roles> 1091: PerlAccessHandler Apache::lonacc 1092: SetHandler perl-script 1093: PerlHandler Apache::lonroles 1094: ErrorDocument 403 /adm/login 1095: ErrorDocument 500 /adm/errorhandler 1096: </Location> 1097: 1098: =head1 OVERVIEW 1099: 1100: =head2 Choosing Roles 1101: 1102: C<lonroles> is a handler that allows a user to switch roles in 1103: mid-session. LON-CAPA attempts to work with "No Role Specified", the 1104: default role that a user has before selecting a role, as widely as 1105: possible, but certain handlers for example need specification which 1106: course they should act on, etc. Both in this scenario, and when the 1107: handler determines via C<lonnet>'s C<&allowed> function that a certain 1108: action is not allowed, C<lonroles> is used as error handler. This 1109: allows the user to select another role which may have permission to do 1110: what they were trying to do. C<lonroles> can also be accessed via the 1111: B<CRS> button in the Remote Control. 1112: 1113: =begin latex 1114: 1115: \begin{figure} 1116: \begin{center} 1117: \includegraphics[width=0.45\paperwidth,keepaspectratio]{Sample_Roles_Screen} 1118: \caption{\label{Sample_Roles_Screen}Sample Roles Screen} 1119: \end{center} 1120: \end{figure} 1121: 1122: =end latex 1123: 1124: =head2 Role Initialization 1125: 1126: The privileges for a user are established at login time and stored in the session environment. As a consequence, a new role does not become active till the next login. Handlers are able to query for privileges using C<lonnet>'s C<&allowed> function. When a user first logs in, their role is the "common" role, which means that they have the sum of all of their privileges. During a session it might become necessary to choose a particular role, which as a consequence also limits the user to only the privileges in that particular role. 1127: 1128: =head1 INTRODUCTION 1129: 1130: This module enables a user to select what role he wishes to 1131: operate under (instructor, student, teaching assistant, course 1132: coordinator, etc). These roles are pre-established by the actions 1133: of upper-level users. 1134: 1135: This is part of the LearningOnline Network with CAPA project 1136: described at http://www.lon-capa.org. 1137: 1138: =head1 HANDLER SUBROUTINE 1139: 1140: This routine is called by Apache and mod_perl. 1141: 1142: =over 4 1143: 1144: =item * 1145: 1146: Roles Initialization (yes/no) 1147: 1148: =item * 1149: 1150: Get Error Message from Environment 1151: 1152: =item * 1153: 1154: Who is this? 1155: 1156: =item * 1157: 1158: Generate Page Output 1159: 1160: =item * 1161: 1162: Choice or no choice 1163: 1164: =item * 1165: 1166: Table 1167: 1168: =item * 1169: 1170: Privileges 1171: 1172: =back 1173: 1174: =cut