![]() ![]() | ![]() |
- Fix typo in 1.240.2.12 backport of 1.242.
1: # The LearningOnline Network with CAPA 2: # User Roles Screen 3: # 4: # $Id: lonroles.pm,v 1.240.2.13 2010/01/18 17:08:57 raeburn 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: =pod 31: 32: =head1 NAME 33: 34: Apache::lonroles - User Roles Screen 35: 36: =head1 SYNOPSIS 37: 38: Invoked by /etc/httpd/conf/srm.conf: 39: 40: <Location /adm/roles> 41: PerlAccessHandler Apache::lonacc 42: SetHandler perl-script 43: PerlHandler Apache::lonroles 44: ErrorDocument 403 /adm/login 45: ErrorDocument 500 /adm/errorhandler 46: </Location> 47: 48: =head1 OVERVIEW 49: 50: =head2 Choosing Roles 51: 52: C<lonroles> is a handler that allows a user to switch roles in 53: mid-session. LON-CAPA attempts to work with "No Role Specified", the 54: default role that a user has before selecting a role, as widely as 55: possible, but certain handlers for example need specification which 56: course they should act on, etc. Both in this scenario, and when the 57: handler determines via C<lonnet>'s C<&allowed> function that a certain 58: action is not allowed, C<lonroles> is used as error handler. This 59: allows the user to select another role which may have permission to do 60: what they were trying to do. C<lonroles> can also be accessed via the 61: B<CRS> button in the Remote Control. 62: 63: =begin latex 64: 65: \begin{figure} 66: \begin{center} 67: \includegraphics[width=0.45\paperwidth,keepaspectratio]{Sample_Roles_Screen} 68: \caption{\label{Sample_Roles_Screen}Sample Roles Screen} 69: \end{center} 70: \end{figure} 71: 72: =end latex 73: 74: =head2 Role Initialization 75: 76: 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. 77: 78: =head1 INTRODUCTION 79: 80: This module enables a user to select what role he wishes to 81: operate under (instructor, student, teaching assistant, course 82: coordinator, etc). These roles are pre-established by the actions 83: of upper-level users. 84: 85: This is part of the LearningOnline Network with CAPA project 86: described at http://www.lon-capa.org. 87: 88: =head1 HANDLER SUBROUTINE 89: 90: This routine is called by Apache and mod_perl. 91: 92: =over 4 93: 94: =item * 95: 96: Roles Initialization (yes/no) 97: 98: =item * 99: 100: Get Error Message from Environment 101: 102: =item * 103: 104: Who is this? 105: 106: =item * 107: 108: Generate Page Output 109: 110: =item * 111: 112: Choice or no choice 113: 114: =item * 115: 116: Table 117: 118: =item * 119: 120: Privileges 121: 122: =back 123: 124: =cut 125: 126: 127: package Apache::lonroles; 128: 129: use strict; 130: use Apache::lonnet; 131: use Apache::lonuserstate(); 132: use Apache::Constants qw(:common); 133: use Apache::File(); 134: use Apache::lonmenu; 135: use Apache::loncommon; 136: use Apache::lonhtmlcommon; 137: use Apache::lonannounce; 138: use Apache::lonlocal; 139: use Apache::lonpageflip(); 140: use Apache::lonnavdisplay(); 141: use Apache::lonmainmenu(); 142: use Apache::loncoursequeueadmin; 143: use GDBM_File; 144: use LONCAPA qw(:DEFAULT :match); 145: use HTML::Entities; 146: 147: 148: sub redirect_user { 149: my ($r,$title,$url,$msg,$launch_nav) = @_; 150: $msg = $title if (! defined($msg)); 151: &Apache::loncommon::content_type($r,'text/html'); 152: &Apache::loncommon::no_cache($r); 153: $r->send_http_header; 154: my $swinfo=&Apache::lonmenu::rawconfig(); 155: my $navwindow; 156: if ($launch_nav eq 'on') { 157: $navwindow.=&Apache::lonnavdisplay::launch_win('now',undef,undef, 158: ($url =~ m-^/adm/whatsnew-)); 159: } else { 160: $navwindow.=&Apache::lonnavmaps::close(); 161: } 162: 163: # Breadcrumbs 164: my $brcrum = [{'href' => $url, 165: 'text' => 'Switching Role'},]; 166: my $start_page = &Apache::loncommon::start_page('Switching Role',undef, 167: {'redirect' => [1,$url], 168: 'bread_crumbs' => $brcrum,}); 169: &Apache::lonhtmlcommon::clear_breadcrumbs(); 170: my $end_page = &Apache::loncommon::end_page(); 171: 172: # Note to style police: 173: # This must only replace the spaces, nothing else, or it bombs elsewhere. 174: $url=~s/ /\%20/g; 175: $r->print(<<ENDREDIR); 176: $start_page 177: <script type="text/javascript"> 178: // <![CDATA[ 179: $swinfo 180: // ]]> 181: </script> 182: $navwindow 183: <p>$msg</p> 184: $end_page 185: ENDREDIR 186: return; 187: } 188: 189: sub error_page { 190: my ($r,$error,$dest)=@_; 191: &Apache::loncommon::content_type($r,'text/html'); 192: &Apache::loncommon::no_cache($r); 193: $r->send_http_header; 194: return OK if $r->header_only; 195: # Breadcrumbs 196: my $brcrum = [{'href' => $dest, 197: 'text' => 'Problems during Course Initialization'},]; 198: $r->print(&Apache::loncommon::start_page('Problems during Course Initialization', 199: undef, 200: {'bread_crumbs' => $brcrum,}) 201: ); 202: $r->print( 203: '<script type="text/javascript">'. 204: '// <![CDATA['. 205: &Apache::lonmenu::rawconfig(). 206: '// ]]>'. 207: '</script>'. 208: '<p class="LC_error">'.&mt('The following problems occurred:'). 209: '<br />'. 210: $error. 211: '</p><br /><a href="'.$dest.'">'.&mt('Continue').'</a>' 212: ); 213: $r->print(&Apache::loncommon::end_page()); 214: } 215: 216: sub handler { 217: 218: my $r = shift; 219: 220: my $now=time; 221: my $then=$env{'user.login.time'}; 222: my $refresh=$env{'user.refresh.time'}; 223: if (!$refresh) { 224: $refresh = $then; 225: } 226: my $envkey; 227: my %dcroles = (); 228: my $numdc = &check_fordc(\%dcroles,$then); 229: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); 230: my $custommenu = &Apache::loncommon::needs_gci_custom(); 231: 232: # ================================================================== Roles Init 233: if ($env{'form.selectrole'}) { 234: 235: my $locknum=&Apache::lonnet::get_locks(); 236: if ($locknum) { return 409; } 237: 238: if ($env{'form.newrole'}) { 239: $env{'form.'.$env{'form.newrole'}}=1; 240: } 241: if ($env{'request.course.id'}) { 242: # Check if user is CC trying to select a course role 243: if ($env{'form.switchrole'}) { 244: if (!defined($env{'user.role.'.$env{'form.switchrole'}})) { 245: &adhoc_course_role($refresh,$then); 246: } 247: } 248: my %temp=('logout_'.$env{'request.course.id'} => time); 249: &Apache::lonnet::put('email_status',\%temp); 250: &Apache::lonnet::delenv('user.state.'.$env{'request.course.id'}); 251: } 252: &Apache::lonnet::appenv({"request.course.id" => '', 253: "request.course.fn" => '', 254: "request.course.uri" => '', 255: "request.course.sec" => '', 256: "request.role" => 'cm', 257: "request.role.adv" => $env{'user.adv'}, 258: "request.role.domain" => $env{'user.domain'}}); 259: # Check if user is a DC trying to enter a course or author space and needs privs to be created 260: if ($numdc > 0) { 261: foreach my $envkey (keys %env) { 262: # Is this an ad-hoc Coordinator role? 263: if (my ($ccrole,$domain,$coursenum) = 264: ($envkey =~ m-^form\.(cc|co)\./($match_domain)/($match_courseid)$-)) { 265: if ($dcroles{$domain}) { 266: &Apache::lonnet::check_adhoc_privs($domain,$coursenum, 267: $then,$refresh,$now,$ccrole); 268: } 269: last; 270: } 271: # Is this an ad-hoc CA-role? 272: if (my ($domain,$user) = 273: ($envkey =~ m-^form\.ca\./($match_domain)/($match_username)$-)) { 274: if (($domain eq $env{'user.domain'}) && ($user eq $env{'user.name'})) { 275: delete($env{$envkey}); 276: $env{'form.au./'.$domain.'/'} = 1; 277: my ($server_status,$home) = &check_author_homeserver($user,$domain); 278: if ($server_status eq 'switchserver') { 279: my $trolecode = 'au./'.$domain.'/'; 280: my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode; 281: $r->internal_redirect($switchserver); 282: } 283: last; 284: } 285: if (my ($castart,$caend) = ($env{'user.role.ca./'.$domain.'/'.$user} =~ /^(\d*)\.(\d*)$/)) { 286: if (((($castart) && ($castart < $now)) || !$castart) && 287: ((!$caend) || (($caend) && ($caend > $now)))) { 288: my ($server_status,$home) = &check_author_homeserver($user,$domain); 289: if ($server_status eq 'switchserver') { 290: my $trolecode = 'ca./'.$domain.'/'.$user; 291: my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode; 292: $r->internal_redirect($switchserver); 293: } 294: last; 295: } 296: } 297: # Check if author blocked ca-access 298: my %blocked=&Apache::lonnet::get('environment',['domcoord.author'],$domain,$user); 299: if ($blocked{'domcoord.author'} eq 'blocked') { 300: delete($env{$envkey}); 301: $env{'user.error.msg'}=':::1:User '.$user.' in domain '.$domain.' blocked domain coordinator access'; 302: last; 303: } 304: if ($dcroles{$domain}) { 305: my ($server_status,$home) = &check_author_homeserver($user,$domain); 306: if (($server_status eq 'ok') || ($server_status eq 'switchserver')) { 307: &Apache::lonnet::check_adhoc_privs($domain,$user,$then, 308: $refresh,$now,'ca'); 309: if ($server_status eq 'switchserver') { 310: my $trolecode = 'ca./'.$domain.'/'.$user; 311: my $switchserver = '/adm/switchserver?' 312: .'otherserver='.$home.'&role='.$trolecode; 313: $r->internal_redirect($switchserver); 314: } 315: } else { 316: delete($env{$envkey}); 317: } 318: } else { 319: delete($env{$envkey}); 320: } 321: last; 322: } 323: } 324: } 325: if (($env{'form.cm'}) && ($env{'form.orgurl'})) { 326: $r->internal_redirect($env{'form.orgurl'}); 327: } 328: foreach $envkey (keys %env) { 329: next if ($envkey!~/^user\.role\./); 330: my ($where,$trolecode,$role,$tstatus,$tend,$tstart); 331: &Apache::lonnet::role_status($envkey,$then,$refresh,$now,\$role,\$where, 332: \$trolecode,\$tstatus,\$tstart,\$tend); 333: if ($env{'form.'.$trolecode}) { 334: if ($tstatus eq 'is') { 335: $where=~s/^\///; 336: my ($cdom,$cnum,$csec)=split(/\//,$where); 337: # check for course groups 338: my %coursegroups = &Apache::lonnet::get_active_groups( 339: $env{'user.domain'},$env{'user.name'},$cdom, $cnum); 340: my $cgrps = join(':',keys(%coursegroups)); 341: 342: # store role if recent_role list being kept 343: if ($env{'environment.recentroles'}) { 344: my %frozen_roles = 345: &Apache::lonhtmlcommon::get_recent_frozen('roles',$env{'environment.recentrolesn'}); 346: &Apache::lonhtmlcommon::store_recent('roles', 347: $trolecode,' ',$frozen_roles{$trolecode}); 348: } 349: 350: 351: # check for keyed access 352: if (($role eq 'st') && 353: ($env{'course.'.$cdom.'_'.$cnum.'.keyaccess'} eq 'yes')) { 354: # who is key authority? 355: my $authdom=$cdom; 356: my $authnum=$cnum; 357: if ($env{'course.'.$cdom.'_'.$cnum.'.keyauth'}) { 358: ($authnum,$authdom)= 359: split(/:/,$env{'course.'.$cdom.'_'.$cnum.'.keyauth'}); 360: } 361: # check with key authority 362: unless (&Apache::lonnet::validate_access_key( 363: $env{'environment.key.'.$cdom.'_'.$cnum}, 364: $authdom,$authnum)) { 365: # there is no valid key 366: if ($env{'form.newkey'}) { 367: # student attempts to register a new key 368: &Apache::loncommon::content_type($r,'text/html'); 369: &Apache::loncommon::no_cache($r); 370: $r->send_http_header; 371: my $swinfo=&Apache::lonmenu::rawconfig(); 372: my $start_page=&Apache::loncommon::start_page 373: ('Verifying Access Key to Unlock this Course'); 374: my $end_page=&Apache::loncommon::end_page(); 375: my $buttontext=&mt('Enter Course'); 376: my $message=&mt('Successfully registered key'); 377: my $assignresult= 378: &Apache::lonnet::assign_access_key( 379: $env{'form.newkey'}, 380: $authdom,$authnum, 381: $cdom,$cnum, 382: $env{'user.domain'}, 383: $env{'user.name'}, 384: &mt('Assigned from [_1] at [_2] for [_3]' 385: ,$ENV{'REMOTE_ADDR'} 386: ,&Apache::lonlocal::locallocaltime() 387: ,$trolecode) 388: ); 389: unless ($assignresult eq 'ok') { 390: $assignresult=~s/^error\:\s*//; 391: $message=&mt($assignresult). 392: '<br /><a href="/adm/logout">'. 393: &mt('Logout').'</a>'; 394: $buttontext=&mt('Re-Enter Key'); 395: } 396: $r->print(<<ENDENTEREDKEY); 397: $start_page 398: <script type="text/javascript"> 399: // <![CDATA[ 400: $swinfo 401: // ]]> 402: </script> 403: <form action="" method="post"> 404: <input type="hidden" name="selectrole" value="1" /> 405: <input type="hidden" name="$trolecode" value="1" /> 406: <span class="LC_fontsize_large">$message</span><br /> 407: <input type="submit" value="$buttontext" /> 408: </form> 409: $end_page 410: ENDENTEREDKEY 411: return OK; 412: } else { 413: # print form to enter a new key 414: &Apache::loncommon::content_type($r,'text/html'); 415: &Apache::loncommon::no_cache($r); 416: $r->send_http_header; 417: my $swinfo=&Apache::lonmenu::rawconfig(); 418: my $start_page=&Apache::loncommon::start_page 419: ('Enter Access Key to Unlock this Course'); 420: my $end_page=&Apache::loncommon::end_page(); 421: $r->print(<<ENDENTERKEY); 422: $start_page 423: <script type="text/javascript"> 424: // <![CDATA[ 425: $swinfo 426: // ]]> 427: </script> 428: <form action="" method="post"> 429: <input type="hidden" name="selectrole" value="1" /> 430: <input type="hidden" name="$trolecode" value="1" /> 431: <input type="text" size="20" name="newkey" value="$env{'form.newkey'}" /> 432: <input type="submit" value="Enter key" /> 433: </form> 434: $end_page 435: ENDENTERKEY 436: return OK; 437: } 438: } 439: } 440: &Apache::lonnet::log($env{'user.domain'}, 441: $env{'user.name'}, 442: $env{'user.home'}, 443: "Role ".$trolecode); 444: 445: &Apache::lonnet::appenv( 446: {'request.role' => $trolecode, 447: 'request.role.domain' => $cdom, 448: 'request.course.sec' => $csec, 449: 'request.course.groups' => $cgrps}); 450: my $tadv=0; 451: 452: if (($cnum) && ($role ne 'ca') && ($role ne 'aa')) { 453: my $msg; 454: if (&Apache::lonnet::allowed('adv') eq 'F') { $tadv=1; } 455: &Apache::lonnet::appenv({'request.role.adv'=>$tadv}); 456: my ($furl,$ferr)= 457: &Apache::lonuserstate::readmap($cdom.'/'.$cnum); 458: if (($env{'form.orgurl'}) && 459: ($env{'form.orgurl'}!~/^\/adm\/flip/)) { 460: my $dest=$env{'form.orgurl'}; 461: if ($env{'form.symb'}) { 462: if ($dest =~ /\?/) { 463: $dest .= '&'; 464: } else { 465: $dest .= '?' 466: } 467: $dest .= 'symb='.$env{'form.symb'}; 468: } 469: if (($ferr) && ($tadv)) { 470: &error_page($r,$ferr,$dest); 471: } else { 472: $r->internal_redirect($dest); 473: } 474: return OK; 475: } else { 476: if (!$env{'request.course.id'}) { 477: &Apache::lonnet::appenv( 478: {"request.course.id" => $cdom.'_'.$cnum}); 479: $furl='/adm/roles?tryagain=1'; 480: $msg='<p><span class="LC_error">' 481: .&mt('Could not initialize [_1] at this time.', 482: $env{'course.'.$cdom.'_'.$cnum.'.description'}) 483: .'</span></p>' 484: .'<p>'.&mt('Please try again.').'</p>' 485: .'<p>'.$ferr.'</p>'; 486: } 487: 488: if (($ferr) && ($tadv)) { 489: &error_page($r,$ferr,$furl); 490: } else { 491: # Check to see if the user is a CC entering a course 492: # for the first time 493: my (undef, undef, $role, $courseid) = split(/\./, $envkey); 494: if (substr($courseid, 0, 1) eq '/') { 495: $courseid = substr($courseid, 1); 496: } 497: $courseid =~ s/\//_/; 498: if (($cdom ne 'gcitest') && (($role eq 'cc') || ($role eq 'co')) 499: && ($env{'course.' . $courseid .'.course.helper.not.run'})) { 500: $furl = "/adm/helper/course.initialization.helper"; 501: # Send the user to the course they selected 502: } elsif ($env{'request.course.id'}) { 503: if ($env{'form.destinationurl'}) { 504: my $dest = $env{'form.destinationurl'}; 505: if ($env{'form.destsymb'} ne '') { 506: my $esc_symb = &HTML::Entities::encode($env{'form.destsymb'},'"<>&'); 507: $dest .= '?symb='.$esc_symb; 508: } 509: &redirect_user($r,&mt('Entering [_1]', 510: $env{'course.'.$courseid.'.description'}), 511: $dest,$msg, 512: $env{'environment.remotenavmap'}); 513: return OK; 514: } 515: if (&Apache::lonnet::allowed('whn', 516: $env{'request.course.id'}) 517: || &Apache::lonnet::allowed('whn', 518: $env{'request.course.id'}.'/' 519: .$env{'request.course.sec'}) 520: ) { 521: my $startpage = &courseloadpage($courseid); 522: unless (($startpage eq 'firstres') || ($cdom eq 'gcitest')) { 523: $msg = &mt('Entering [_1] ...', 524: $env{'course.'.$courseid.'.description'}); 525: &redirect_user($r,&mt('New in course'), 526: '/adm/whatsnew?refpage=start',$msg, 527: $env{'environment.remotenavmap'}); 528: return OK; 529: } 530: } 531: } 532: # Are we allowed to look at the first resource? 533: if ($furl !~ m|^/adm/|) { 534: # Guess not ... 535: $furl=&Apache::lonpageflip::first_accessible_resource(); 536: } 537: if (($cdom eq 'gcitest') && ($custommenu)) { 538: $furl = '/adm/navmaps'; 539: } 540: $msg = &mt('Entering [_1] ...', 541: $env{'course.'.$courseid.'.description'}); 542: &redirect_user($r,&mt('Entering [_1]', 543: $env{'course.'.$courseid.'.description'}), 544: $furl,$msg, 545: $env{'environment.remotenavmap'}); 546: } 547: return OK; 548: } 549: } 550: # 551: # Send the user to the construction space they selected 552: if ($role =~ /^(au|ca|aa)$/) { 553: my $redirect_url = '/priv/'; 554: if ($role eq 'au') { 555: $redirect_url.=$env{'user.name'}; 556: } else { 557: $where =~ /\/(.*)$/; 558: $redirect_url .= $1; 559: } 560: $redirect_url .= '/'; 561: &redirect_user($r,&mt('Entering Construction Space'), 562: $redirect_url); 563: return OK; 564: } 565: if ($role eq 'dc') { 566: my $redirect_url = '/adm/menu/'; 567: &redirect_user($r,&mt('Loading Domain Coordinator Menu'), 568: $redirect_url); 569: return OK; 570: } 571: if ($role eq 'sc') { 572: my $redirect_url = '/adm/grades?command=scantronupload'; 573: &redirect_user($r,&mt('Loading Data Upload Page'), 574: $redirect_url); 575: return OK; 576: } 577: } 578: } 579: } 580: } 581: 582: # =============================================================== No Roles Init 583: 584: &Apache::loncommon::content_type($r,'text/html'); 585: &Apache::loncommon::no_cache($r); 586: $r->send_http_header; 587: return OK if $r->header_only; 588: 589: my ($crumbtext,$pagetitle,$recent,$show_course); 590: my $noscript='<span class="LC_error">'.&mt('Use of LON-CAPA requires Javascript to be enabled in your web browser.').'<br />'.&mt('As this is not the case, most functionality in the system will be unavailable.').'</span><br />'; 591: if ($custommenu) { 592: my $start_page = &Apache::loncommon::start_page('Main Menu',undef, 593: {'bread_crumbs' => 1}); 594: $r->print(<<"ENDCUSTOM"); 595: $start_page 596: <br /> 597: <noscript> 598: $noscript 599: </noscript> 600: ENDCUSTOM 601: } else { 602: $crumbtext = 'User Roles'; 603: $pagetitle = 'My Roles'; 604: $recent = &mt('Recent Roles'); 605: $show_course=&Apache::loncommon::show_course(); 606: if ($show_course) { 607: $crumbtext = 'Courses'; 608: $pagetitle = 'My Courses'; 609: $recent = &mt('Recent Courses'); 610: } 611: my $brcrum =[{href=>"/adm/roles",text=>$crumbtext}]; 612: my $swinfo=&Apache::lonmenu::rawconfig(); 613: my $start_page=&Apache::loncommon::start_page($pagetitle,undef,{bread_crumbs=>$brcrum}); 614: my $standby=&mt('Role selected. Please stand by.'); 615: $standby=~s/\n/\\n/g; 616: $r->print(<<ENDHEADER); 617: $start_page 618: <br /> 619: <noscript> 620: $noscript 621: </noscript> 622: <script type="text/javascript"> 623: // <![CDATA[ 624: $swinfo 625: window.focus(); 626: 627: active=true; 628: 629: function enterrole (thisform,rolecode,buttonname) { 630: if (active) { 631: active=false; 632: document.title='$standby'; 633: window.status='$standby'; 634: thisform.newrole.value=rolecode; 635: thisform.submit(); 636: } else { 637: alert('$standby'); 638: } 639: } 640: // ]]> 641: </script> 642: ENDHEADER 643: } 644: 645: # ------------------------------------------ Get Error Message from Environment 646: 647: my ($fn,$priv,$nochoose,$error,$msg)=split(/:/,$env{'user.error.msg'}); 648: if ($env{'user.error.msg'}) { 649: $r->log_reason( 650: "$msg for $env{'user.name'} domain $env{'user.domain'} access $priv",$fn); 651: } 652: 653: # ------------------------------------------------- Can this user re-init, etc? 654: 655: my $advanced=$env{'user.adv'}; 656: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['tryagain']); 657: my $tryagain=$env{'form.tryagain'}; 658: my $reinit=$env{'user.reinit'}; 659: delete $env{'user.reinit'}; 660: 661: # -------------------------------------------------------- Generate Page Output 662: # --------------------------------------------------------------- Error Header? 663: if ($error) { 664: $r->print("<h1>".&mt('LON-CAPA Access Control')."</h1>"); 665: $r->print("<!-- LONCAPAACCESSCONTROLERRORSCREEN --><hr /><pre>"); 666: if ($priv ne '') { 667: $r->print(&mt('Access : ').&Apache::lonnet::plaintext($priv)."\n"); 668: } 669: if ($fn ne '') { 670: $r->print(&mt('Resource: ').&Apache::lonenc::check_encrypt($fn)."\n"); 671: } 672: if ($msg ne '') { 673: $r->print(&mt('Action : ').$msg."\n"); 674: } 675: $r->print("</pre><hr />"); 676: my $url=$fn; 677: my $last; 678: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', 679: &GDBM_READER(),0640)) { 680: $last=$hash{'last_known'}; 681: untie(%hash); 682: } 683: if ($last) { $fn.='?symb='.&escape($last); } 684: 685: &Apache::londocs::changewarning($r,undef,'You have modified your course recently, [_1] may fix this access problem.', 686: &Apache::lonenc::check_encrypt($fn)); 687: } else { 688: if ($env{'user.error.msg'}) { 689: if ($reinit) { 690: $r->print( 691: '<h3><span class="LC_error">'. 692: &mt('As your session file for the course or community has expired, you will need to re-select it.').'</span></h3>'); 693: } else { 694: $r->print( 695: '<h3><span class="LC_error">'. 696: &mt('You need to choose another user role or enter a specific course or community for this function.'). 697: '</span></h3>'); 698: } 699: } 700: } 701: # -------------------------------------------------------- Choice or no choice? 702: if ($nochoose) { 703: $r->print("<h2>".&mt('Sorry ...')."</h2>\n<span class='LC_error'>". 704: &mt('This action is currently not authorized.').'</span>'. 705: &Apache::loncommon::end_page()); 706: return OK; 707: } else { 708: if (($ENV{'REDIRECT_QUERY_STRING'}) && ($fn)) { 709: $fn.='?'.$ENV{'REDIRECT_QUERY_STRING'}; 710: } 711: unless ($custommenu) { 712: $r->print('<form method="post" name="rolechoice" action="'.(($fn)?$fn:$r->uri).'">'); 713: $r->print('<input type="hidden" name="orgurl" value="'.$fn.'" />'); 714: $r->print('<input type="hidden" name="selectrole" value="1" />'); 715: $r->print('<input type="hidden" name="newrole" value="" />'); 716: } 717: } 718: 719: my (%roletext,%sortrole,%roleclass,%futureroles,%timezones); 720: my ($countactive,$countfuture,$inrole,$possiblerole) = 721: &gather_roles($then,$refresh,$now,$reinit,$nochoose,\%roletext,\%sortrole,\%roleclass, 722: \%futureroles,\%timezones); 723: 724: $refresh = $now; 725: &Apache::lonnet::appenv({'user.refresh.time' => $refresh}); 726: if (!$countactive && !$countfuture) { 727: if (&Apache::loncommon::new_roles_update()) { 728: ($countactive,$countfuture,$inrole,$possiblerole) = 729: &gather_roles($then,$refresh,$now,$reinit,$nochoose,\%roletext,\%sortrole, 730: \%roleclass,\%futureroles,\%timezones); 731: } 732: } 733: if ($custommenu) { 734: if ($env{'form.destinationurl'} eq '/adm/gci_info') { 735: $r->print(&gci_info_page()). 736: &Apache::loncommon::end_page(); 737: return OK; 738: } 739: my %courses = &Apache::loncommon::existing_gcitest_courses('cc'); 740: $env{'browser.interface'}='faketextual'; 741: $env{'environment.remote'}='off'; 742: my $numcourses = keys(%courses); 743: my $switcher; 744: if ($numcourses > 0) { 745: $switcher = &Apache::lonmainmenu::gcitest_switcher('cc',%courses); 746: my $current; 747: if ($env{'request.course.id'}) { 748: $current = 'cc./'.$env{'course.'.$env{'request.course.id'}.'.domain'}. 749: '/'.$env{'course.'.$env{'request.course.id'}.'.num'}; 750: } 751: my $switcher_js = &Apache::lonmainmenu::gcitest_switcher_js($current,$numcourses); 752: $r->print(<<"ENDSCRIPT"); 753: <script type="text/javascript"> 754: // <![CDATA[ 755: $switcher_js 756: // ]]> 757: </script> 758: ENDSCRIPT 759: } 760: $r->print(&Apache::lonmenu::inlinemenu('gcicustom',$switcher). 761: &Apache::loncommon::end_page()); 762: return OK; 763: } else { 764: if ($env{'form.destinationurl'} eq '/adm/gci_info') { 765: delete($env{'form.destinationurl'}); 766: } 767: } 768: if ($env{'user.adv'}) { 769: $r->print('<p><label><input type="checkbox" name="showall"'); 770: if ($env{'form.showall'}) { $r->print(' checked="checked" '); } 771: $r->print(' />'.&mt('Show all roles').'</label>' 772: .' <input type="submit" value="'.&mt('Update display').'" />' 773: .'</p>'); 774: } else { 775: if ($countactive > 0) { 776: $r->print(&Apache::loncoursequeueadmin::queued_selfenrollment()); 777: my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); 778: my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); 779: unless ($env{'user.domain'} eq 'gcitest') { 780: $r->print( 781: '<p>' 782: .&mt('[_1]Visit the [_2]Course/Community Catalog[_3]' 783: .' to view all [_4] LON-CAPA courses and communities.' 784: ,'<b>' 785: ,'<a href="/adm/coursecatalog?showdom='.$esc_dom.'">' 786: ,'</a></b>',$domdesc) 787: .'<br />' 788: .&mt('If a course or community is [_1]not[_2] in your list of current courses and communities below,' 789: .' you may be able to enroll if self-enrollment is permitted.' 790: ,'<b>','</b>') 791: .'</p>' 792: ); 793: } 794: } 795: } 796: 797: # No active roles 798: if ($countactive==0) { 799: if ($inrole) { 800: $r->print('<h2>'.&mt('Currently no additional roles, courses or communities').'</h2>'); 801: } else { 802: $r->print('<h2>'.&mt('Currently no active roles, courses or communities').'</h2>'); 803: } 804: unless ($env{'user.domain'} eq 'gcitest') { 805: &findcourse_advice($r); 806: &requestcourse_advice($r); 807: } 808: $r->print('</form>'); 809: if ($countfuture) { 810: $r->print(&mt('The following [quant,_1,role,roles] will become active in the future:',$countfuture)); 811: my $doheaders = &roletable_headers($r,\%roleclass,\%sortrole, 812: $nochoose); 813: &print_rolerows($r,$doheaders,\%roleclass,\%sortrole,\%dcroles, 814: \%roletext); 815: my $tremark=''; 816: my $tbg; 817: if ($env{'request.role'} eq 'cm') { 818: $tbg="LC_roles_selected"; 819: $tremark=&mt('Currently selected.').' '; 820: } else { 821: $tbg="LC_roles_is"; 822: } 823: $r->print(&Apache::loncommon::start_data_table_row() 824: .'<td class="'.$tbg.'"> </td>' 825: .'<td colspan="3">' 826: .&mt('No role specified') 827: .'</td>' 828: .'<td>'.$tremark.' </td>' 829: .&Apache::loncommon::end_data_table_row() 830: ); 831: 832: $r->print(&Apache::loncommon::end_data_table()); 833: } 834: $r->print(&Apache::loncommon::end_page()); 835: return OK; 836: } elsif ($countactive==1) { # Is there only one choice? 837: my $needs_switchserver; 838: if ($env{'user.author'}) { 839: $needs_switchserver = &check_needs_switchserver($possiblerole); 840: } 841: if ((!$needs_switchserver) && ($env{'request.role'} eq 'cm')) { 842: $r->print('<h3>'.&mt('Please stand by.').'</h3>'. 843: '<input type="hidden" name="'.$possiblerole.'" value="1" />'. 844: '<noscript><br /><input type="submit" name="submit" value="'.&mt('Continue').'" /></noscript>'); 845: $r->print("</form>\n"); 846: $r->rflush(); 847: $r->print('<script type="text/javascript">document.forms.rolechoice.submit();</script>'); 848: $r->print(&Apache::loncommon::end_page()); 849: return OK; 850: } 851: if ($needs_switchserver) { 852: $r->print("<h2>".&mt('Server Switch Required')."</h2>\n". 853: &mt('Construction Space access is only available from '. 854: 'the home server of the corresponding Author.').'<br />'. 855: &mt("Click the 'Switch Server' link to go there.").'<br />'); 856: } 857: } 858: # ----------------------------------------------------------------------- Table 859: unless ((!&Apache::loncommon::show_course()) || ($nochoose) || ($countactive==1)) { 860: $r->print("<h2>".&mt('Select a Course to Enter')."</h2>\n"); 861: } 862: if ($env{'form.destinationurl'}) { 863: $r->print('<input type="hidden" name="destinationurl" value="'. 864: $env{'form.destinationurl'}.'" />'); 865: if ($env{'form.destsymb'} ne '') { 866: $r->print('<input type="hidden" name="destsymb" value="'. 867: $env{'form.destsymb'}.'" />'); 868: } 869: } 870: my $doheaders = &roletable_headers($r,\%roleclass,\%sortrole,$nochoose); 871: if ($env{'environment.recentroles'}) { 872: my %recent_roles = 873: &Apache::lonhtmlcommon::get_recent('roles',$env{'environment.recentrolesn'}); 874: my $output=''; 875: foreach (sort(keys(%recent_roles))) { 876: if (ref($roletext{'user.role.'.$_}) eq 'ARRAY') { 877: $output.= &Apache::loncommon::start_data_table_row(). 878: $roletext{'user.role.'.$_}->[0]. 879: &Apache::loncommon::end_data_table_row(). 880: &Apache::loncommon::continue_data_table_row(). 881: $roletext{'user.role.'.$_}->[1]. 882: &Apache::loncommon::end_data_table_row(); 883: if ($_ =~ m-dc\./($match_domain)/- 884: && $dcroles{$1}) { 885: $output .= &adhoc_roles_row($1,'recent'); 886: } 887: } elsif ($numdc > 0) { 888: unless ($_ =~/^error\:/) { 889: $output.=&display_cc_role('user.role.'.$_); 890: } 891: } 892: } 893: if ($output) { 894: $r->print(&Apache::loncommon::start_data_table_empty_row() 895: .'<td align="center" colspan="5">' 896: .$recent 897: .'</td>' 898: .&Apache::loncommon::end_data_table_empty_row() 899: ); 900: $r->print($output); 901: $doheaders ++; 902: } 903: } 904: 905: if ($numdc > 0) { 906: $r->print(&coursepick_jscript()); 907: $r->print(&Apache::loncommon::coursebrowser_javascript(). 908: &Apache::loncommon::authorbrowser_javascript()); 909: } 910: &print_rolerows($r,$doheaders,\%roleclass,\%sortrole,\%dcroles,\%roletext); 911: if ($countactive > 1) { 912: my $tremark=''; 913: my $tbg; 914: if ($env{'request.role'} eq 'cm') { 915: $tbg="LC_roles_selected"; 916: $tremark=&mt('Currently selected.').' '; 917: } else { 918: $tbg="LC_roles_is"; 919: } 920: $r->print(&Apache::loncommon::start_data_table_row()); 921: unless ($nochoose) { 922: if ($env{'request.role'} ne 'cm') { 923: $r->print('<td class="'.$tbg.'"><input type="submit" value="'. 924: &mt('Select').'" name="cm" /></td>'); 925: } else { 926: $r->print('<td class="'.$tbg.'"> </td>'); 927: } 928: } 929: $r->print('<td colspan="3">' 930: .&mt('No role specified') 931: .'</td>' 932: .'<td>'.$tremark.' </td>' 933: .&Apache::loncommon::end_data_table_row() 934: ); 935: } 936: $r->print(&Apache::loncommon::end_data_table()); 937: unless ($nochoose) { 938: $r->print("</form>\n"); 939: } 940: # ------------------------------------------------------------ Privileges Info 941: if (($advanced) && (($env{'user.error.msg'}) || ($error))) { 942: $r->print('<hr /><h2>'.&mt('Current Privileges').'</h2>'); 943: $r->print(&privileges_info()); 944: } 945: $r->print(&Apache::lonnet::getannounce()); 946: if ($advanced) { 947: my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); 948: $r->print('<p><small><i>' 949: .&mt('This LON-CAPA server is version [_1]',$r->dir_config('lonVersion')) 950: .'</i><br />' 951: .'<a href="/adm/logout">'.&mt('Logout').'</a> ' 952: .'<a href="/adm/coursecatalog?showdom='.$esc_dom.'">' 953: .&mt('Course/Community Catalog') 954: .'</a></small></p>'); 955: } 956: $r->print(&Apache::loncommon::end_page()); 957: return OK; 958: } 959: 960: sub gci_info_page { 961: return <<"END"; 962: <h2>Welcome to the Geoscience Concept Inventory WebCenter</h2> 963: <p> 964: Use the tabs to navigate the WebCenter and... 965: <ul> 966: <li>Review and comment on existing GCI questions</li> 967: <li>Submit a GCI question of your own</li> 968: <li>Create an online test for your students</li> 969: </ul> 970: </p> 971: <p>For more information about writing and reviewing Concept Inventory questions 972: please refer to the <a href="/res/gci/gci/internal/pdfs/GCIWorkbook.pdf">GCI Workbook</a>. 973: 974: END 975: } 976: 977: sub gather_roles { 978: my ($then,$refresh,$now,$reinit,$nochoose,$roletext,$sortrole,$roleclass,$futureroles,$timezones) = @_; 979: my ($countactive,$countfuture,$inrole,$possiblerole) = (0,0,0,''); 980: my $advanced = $env{'user.adv'}; 981: my $tryagain = $env{'form.tryagain'}; 982: foreach my $envkey (sort(keys(%env))) { 983: my $button = 1; 984: my $switchserver=''; 985: my ($role_text,$role_text_end,$sortkey); 986: if ($envkey=~/^user\.role\./) { 987: my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend); 988: &Apache::lonnet::role_status($envkey,$then,$refresh,$now,\$role,\$where, 989: \$trolecode,\$tstatus,\$tstart,\$tend); 990: next if (!defined($role) || $role eq '' || $role =~ /^gr/); 991: my $timezone = &role_timezone($where,$timezones); 992: $tremark=''; 993: $tpstart=' '; 994: $tpend=' '; 995: if ($tstart) { 996: $tpstart=&Apache::lonlocal::locallocaltime($tstart,$timezone); 997: } 998: if ($tend) { 999: $tpend=&Apache::lonlocal::locallocaltime($tend,$timezone); 1000: } 1001: if ($env{'request.role'} eq $trolecode) { 1002: $tstatus='selected'; 1003: } 1004: my $tbg; 1005: if (($tstatus eq 'is') 1006: || ($tstatus eq 'selected') 1007: || ($tstatus eq 'future') 1008: || ($env{'form.showall'})) { 1009: if ($tstatus eq 'is') { 1010: $tbg='LC_roles_is'; 1011: $possiblerole=$trolecode; 1012: $countactive++; 1013: } elsif ($tstatus eq 'future') { 1014: $tbg='LC_roles_future'; 1015: $button=0; 1016: $futureroles->{$trolecode} = $tstart.':'.$tend; 1017: $countfuture ++; 1018: } elsif ($tstatus eq 'expired') { 1019: $tbg='LC_roles_expired'; 1020: $button=0; 1021: } elsif ($tstatus eq 'will_not') { 1022: $tbg='LC_roles_will_not'; 1023: $tremark.=&mt('Expired after logout.').' '; 1024: } elsif ($tstatus eq 'selected') { 1025: $tbg='LC_roles_selected'; 1026: $inrole=1; 1027: $countactive++; 1028: $tremark.=&mt('Currently selected.').' '; 1029: } 1030: my $trole; 1031: if ($role =~ /^cr\//) { 1032: my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$role); 1033: if ($tremark) { $tremark.='<br />'; } 1034: $tremark.=&mt('Defined by [_1] at [_2].',$rauthor,$rdomain); 1035: } 1036: $trole=Apache::lonnet::plaintext($role); 1037: my $ttype; 1038: my $twhere; 1039: my ($tdom,$trest,$tsection)= 1040: split(/\//,Apache::lonnet::declutter($where)); 1041: # First, Co-Authorship roles 1042: if (($role eq 'ca') || ($role eq 'aa')) { 1043: my $home = &Apache::lonnet::homeserver($trest,$tdom); 1044: my $allowed=0; 1045: my @ids=&Apache::lonnet::current_machine_ids(); 1046: foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } 1047: if (!$allowed) { 1048: $button=0; 1049: $switchserver='otherserver='.$home.'&role='.$trolecode; 1050: } 1051: #next if ($home eq 'no_host'); 1052: $home = &Apache::lonnet::hostname($home); 1053: $ttype='Construction Space'; 1054: $twhere=&mt('User').': '.$trest.'<br />'.&mt('Domain'). 1055: ': '.$tdom.'<br />'. 1056: ' '.&mt('Server').': '.$home; 1057: $env{'course.'.$tdom.'_'.$trest.'.description'}='ca'; 1058: $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$trest.'/'); 1059: $sortkey=$role."$trest:$tdom"; 1060: } elsif ($role eq 'au') { 1061: # Authors 1062: my $home = &Apache::lonnet::homeserver 1063: ($env{'user.name'},$env{'user.domain'}); 1064: my $allowed=0; 1065: my @ids=&Apache::lonnet::current_machine_ids(); 1066: foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } 1067: if (!$allowed) { 1068: $button=0; 1069: $switchserver='otherserver='.$home.'&role='.$trolecode; 1070: } 1071: #next if ($home eq 'no_host'); 1072: $home = &Apache::lonnet::hostname($home); 1073: $ttype='Construction Space'; 1074: $twhere=&mt('Domain').': '.$tdom.'<br />'.&mt('Server'). 1075: ': '.$home; 1076: $env{'course.'.$tdom.'_'.$trest.'.description'}='ca'; 1077: $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$env{'user.name'}.'/'); 1078: $sortkey=$role; 1079: } elsif ($trest) { 1080: my $tcourseid=$tdom.'_'.$trest; 1081: $ttype = &Apache::loncommon::course_type($tcourseid); 1082: $trole = &Apache::lonnet::plaintext($role,$ttype,$tcourseid); 1083: if ($env{'course.'.$tcourseid.'.description'}) { 1084: $twhere=$env{'course.'.$tcourseid.'.description'}; 1085: $sortkey=$role."\0".$tdom."\0".$twhere."\0".$envkey; 1086: unless ($twhere eq &mt('Currently not available')) { 1087: $twhere.=' <span class="LC_fontsize_small">'. 1088: &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom). 1089: '</span>'; 1090: } 1091: } else { 1092: my %newhash=&Apache::lonnet::coursedescription($tcourseid); 1093: if (%newhash) { 1094: $sortkey=$role."\0".$tdom."\0".$newhash{'description'}. 1095: "\0".$envkey; 1096: $twhere=$newhash{'description'}. 1097: ' <span class="LC_fontsize_small">'. 1098: &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom). 1099: '</span>'; 1100: $ttype = $newhash{'type'}; 1101: $trole = &Apache::lonnet::plaintext($role,$ttype,$tcourseid); 1102: } else { 1103: $twhere=&mt('Currently not available'); 1104: $env{'course.'.$tcourseid.'.description'}=$twhere; 1105: $sortkey=$role."\0".$tdom."\0".$twhere."\0".$envkey; 1106: $ttype = 'Unavailable'; 1107: } 1108: } 1109: if ($tsection) { 1110: $twhere.='<br />'.&mt('Section').': '.$tsection; 1111: } 1112: if ($role ne 'st') { $twhere.="<br />".&mt('Domain').":".$tdom; } 1113: } elsif ($tdom) { 1114: $ttype='Domain'; 1115: $twhere=$tdom; 1116: $sortkey=$role.$twhere; 1117: } else { 1118: $ttype='System'; 1119: $twhere=&mt('system wide'); 1120: $sortkey=$role.$twhere; 1121: } 1122: ($role_text,$role_text_end) = 1123: &build_roletext($trolecode,$tdom,$trest,$tstatus,$tryagain, 1124: $advanced,$tremark,$tbg,$trole,$twhere,$tpstart, 1125: $tpend,$nochoose,$button,$switchserver,$reinit); 1126: $roletext->{$envkey}=[$role_text,$role_text_end]; 1127: if (!$sortkey) {$sortkey=$twhere."\0".$envkey;} 1128: $sortrole->{$sortkey}=$envkey; 1129: $roleclass->{$envkey}=$ttype; 1130: } 1131: } 1132: } 1133: return ($countactive,$countfuture,$inrole,$possiblerole); 1134: } 1135: 1136: sub role_timezone { 1137: my ($where,$timezones) = @_; 1138: my $timezone; 1139: if (ref($timezones) eq 'HASH') { 1140: if ($where =~ m{^/($match_domain)/($match_courseid)}) { 1141: my $cdom = $1; 1142: my $cnum = $2; 1143: if ($cdom && $cnum) { 1144: if (!exists($timezones->{$cdom.'_'.$cnum})) { 1145: my %timehash = 1146: &Apache::lonnet::get('environment',['timezone'],$cdom,$cnum); 1147: if ($timehash{'timezone'} eq '') { 1148: if (!exists($timezones->{$cdom})) { 1149: my %domdefaults = 1150: &Apache::lonnet::get_domain_defaults($cdom); 1151: if ($domdefaults{'timezone_def'} eq '') { 1152: $timezones->{$cdom} = 'local'; 1153: } else { 1154: $timezones->{$cdom} = $domdefaults{'timezone_def'}; 1155: } 1156: } 1157: $timezones->{$cdom.'_'.$cnum} = $timezones->{$cdom}; 1158: } else { 1159: $timezones->{$cdom.'_'.$cnum} = 1160: &Apache::lonlocal::gettimezone($timehash{'timezone'}); 1161: } 1162: } 1163: $timezone = $timezones->{$cdom.'_'.$cnum}; 1164: } 1165: } else { 1166: my ($tdom) = ($where =~ m{^/($match_domain)}); 1167: if ($tdom) { 1168: if (!exists($timezones->{$tdom})) { 1169: my %domdefaults = &Apache::lonnet::get_domain_defaults($tdom); 1170: if ($domdefaults{'timezone_def'} eq '') { 1171: $timezones->{$tdom} = 'local'; 1172: } else { 1173: $timezones->{$tdom} = $domdefaults{'timezone_def'}; 1174: } 1175: } 1176: $timezone = $timezones->{$tdom}; 1177: } 1178: } 1179: if ($timezone eq 'local') { 1180: $timezone = undef; 1181: } 1182: } 1183: return $timezone; 1184: } 1185: 1186: sub roletable_headers { 1187: my ($r,$roleclass,$sortrole,$nochoose) = @_; 1188: my $doheaders; 1189: if ((ref($sortrole) eq 'HASH') && (ref($roleclass) eq 'HASH')) { 1190: $r->print('<br />' 1191: .&Apache::loncommon::start_data_table() 1192: .&Apache::loncommon::start_data_table_header_row() 1193: ); 1194: if (!$nochoose) { $r->print('<th> </th>'); } 1195: $r->print('<th>'.&mt('User Role').'</th>' 1196: .'<th>'.&mt('Extent').'</th>' 1197: .'<th>'.&mt('Start').'</th>' 1198: .'<th>'.&mt('End').'</th>' 1199: .&Apache::loncommon::end_data_table_header_row() 1200: ); 1201: $doheaders=-1; 1202: my @roletypes = &roletypes(); 1203: foreach my $type (@roletypes) { 1204: my $haverole=0; 1205: foreach my $which (sort {uc($a) cmp uc($b)} (keys(%{$sortrole}))) { 1206: if ($roleclass->{$sortrole->{$which}} =~ /^\Q$type\E/) { 1207: $haverole=1; 1208: } 1209: } 1210: if ($haverole) { $doheaders++; } 1211: } 1212: } 1213: return $doheaders; 1214: } 1215: 1216: sub roletypes { 1217: my @types = ('Domain','Construction Space','Course','Community','Unavailable','System'); 1218: return @types; 1219: } 1220: 1221: sub print_rolerows { 1222: my ($r,$doheaders,$roleclass,$sortrole,$dcroles,$roletext) = @_; 1223: if ((ref($roleclass) eq 'HASH') && (ref($sortrole) eq 'HASH')) { 1224: my @types = &roletypes(); 1225: foreach my $type (@types) { 1226: my $output; 1227: foreach my $which (sort {uc($a) cmp uc($b)} (keys(%{$sortrole}))) { 1228: if ($roleclass->{$sortrole->{$which}} =~ /^\Q$type\E/) { 1229: if (ref($roletext) eq 'HASH') { 1230: if (ref($roletext->{$sortrole->{$which}}) eq 'ARRAY') { 1231: $output.= &Apache::loncommon::start_data_table_row(). 1232: $roletext->{$sortrole->{$which}}->[0]. 1233: &Apache::loncommon::end_data_table_row(). 1234: &Apache::loncommon::continue_data_table_row(). 1235: $roletext->{$sortrole->{$which}}->[1]. 1236: &Apache::loncommon::end_data_table_row(); 1237: } 1238: if ($sortrole->{$which} =~ m-dc\./($match_domain)/-) { 1239: if (ref($dcroles) eq 'HASH') { 1240: if ($dcroles->{$1}) { 1241: $output .= &adhoc_roles_row($1,''); 1242: } 1243: } 1244: } 1245: } 1246: } 1247: } 1248: if ($output) { 1249: if ($doheaders > 0) { 1250: $r->print(&Apache::loncommon::start_data_table_empty_row() 1251: .'<td align="center" colspan="5">' 1252: .&mt($type) 1253: .'</td>' 1254: .&Apache::loncommon::end_data_table_empty_row() 1255: ); 1256: } 1257: $r->print($output); 1258: } 1259: } 1260: } 1261: } 1262: 1263: sub findcourse_advice { 1264: my ($r) = @_; 1265: my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); 1266: my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); 1267: if (&Apache::lonnet::auto_run(undef,$env{'user.domain'})) { 1268: $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).' 1269: <ul> 1270: <li>'.&mt('The course has yet to be created.').'</li> 1271: <li>'.&mt('Automatic enrollment of registered students has not been enabled for the course.').'</li> 1272: <li>'.&mt('You are in a section of course for which automatic enrollment in the corresponding LON-CAPA course is not active.').'</li> 1273: <li>'.&mt('The start date for automated enrollment has yet to be reached.').'</li> 1274: <li>'.&mt('You registered for the course recently and there is a time lag between the time you register, and the time this information becomes available for the update of LON-CAPA course rosters.').'</li> 1275: </ul>'); 1276: } else { 1277: $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.').'<br />'); 1278: } 1279: $r->print('<h3>'.&mt('Self-Enrollment').'</h3>'. 1280: '<p>'.&mt('The [_1]Course/Community Catalog[_2] provides information about all [_3] classes for which LON-CAPA courses have been created, as well as any communities in the domain.','<a href="/adm/coursecatalog?showdom='.$esc_dom.'">','</a>',$domdesc).'<br />'); 1281: $r->print(&mt('You can search for courses and communities which permit self-enrollment, if you would like to enroll in one.').'</p>'. 1282: &Apache::loncoursequeueadmin::queued_selfenrollment()); 1283: return; 1284: } 1285: 1286: sub requestcourse_advice { 1287: my ($r) = @_; 1288: my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); 1289: my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); 1290: my (%can_request,%request_doms); 1291: &Apache::lonnet::check_can_request($env{'user.domain'},\%can_request,\%request_doms); 1292: if (keys(%request_doms) > 0) { 1293: my ($types,$typename) = &Apache::loncommon::course_types(); 1294: if ((ref($types) eq 'ARRAY') && (ref($typename) eq 'HASH')) { 1295: $r->print('<h3>'.&mt('Request creation of a course or community').'</h3>'. 1296: '<p>'.&mt('You have rights to request the creation of courses and/or communities in the following domain(s):').'<ul>'); 1297: my (@reqdoms,@reqtypes); 1298: foreach my $type (sort(keys(%request_doms))) { 1299: push(@reqtypes,$type); 1300: if (ref($request_doms{$type}) eq 'ARRAY') { 1301: my $domstr = join(', ',map { &Apache::lonnet::domain($_) } sort(@{$request_doms{$type}})); 1302: $r->print( 1303: '<li>' 1304: .&mt('[_1]'.$typename->{$type}.'[_2] in domain: [_3]', 1305: '<i>', 1306: '</i>', 1307: '<b>'.$domstr.'</b>') 1308: .'</li>' 1309: ); 1310: foreach my $dom (@{$request_doms{$type}}) { 1311: unless (grep(/^\Q$dom\E/,@reqdoms)) { 1312: push(@reqdoms,$dom); 1313: } 1314: } 1315: } 1316: } 1317: my @showtypes; 1318: foreach my $type (@{$types}) { 1319: if (grep(/^\Q$type\E$/,@reqtypes)) { 1320: push(@showtypes,$type); 1321: } 1322: } 1323: my $requrl = '/adm/requestcourse'; 1324: if (@reqdoms == 1) { 1325: $requrl .= '?showdom='.$reqdoms[0]; 1326: } 1327: if (@showtypes > 0) { 1328: $requrl.=(($requrl=~/\?/)?'&':'?').'crstype='.$showtypes[0]; 1329: } 1330: if (@reqdoms == 1 || @showtypes > 0) { 1331: $requrl .= '&state=crstype&action=new'; 1332: } 1333: $r->print('</ul>'.&mt('Use the [_1]request form[_2] to submit a request for creation of a new course or community.','<a href="'.$requrl.'">','</a>').'</p>'); 1334: } 1335: } 1336: return; 1337: } 1338: 1339: sub queued_selfenrollment { 1340: my ($r) = @_; 1341: my %selfenrollrequests = &Apache::lonnet::dump('selfenrollrequests'); 1342: my %reqs_by_date; 1343: foreach my $item (keys(%selfenrollrequests)) { 1344: if (ref($selfenrollrequests{$item}) eq 'HASH') { 1345: if ($selfenrollrequests{$item}{'status'} eq 'request') { 1346: if ($selfenrollrequests{$item}{'timestamp'}) { 1347: push(@{$reqs_by_date{$selfenrollrequests{$item}{'timestamp'}}},$item); 1348: } 1349: } 1350: } 1351: } 1352: if (keys(%reqs_by_date)) { 1353: my $rolename = &Apache::lonnet::plaintext('st'); 1354: $r->print('<b>'.&mt('Enrollment requests pending Course Coordinator approval').'</b><br />'. 1355: &Apache::loncommon::start_data_table(). 1356: &Apache::loncommon::start_data_table_header_row(). 1357: '<th>'.&mt('Date requested').'</th><th>'.&mt('Course title').'</th>'. 1358: '<th>'.&mt('User role').'</th><th>'.&mt('Section').'</th>'. 1359: &Apache::loncommon::end_data_table_header_row()); 1360: my @sorted = sort { $a <=> $b } (keys(%reqs_by_date)); 1361: foreach my $item (@sorted) { 1362: if (ref($reqs_by_date{$item}) eq 'ARRAY') { 1363: foreach my $crs (@{$reqs_by_date{$item}}) { 1364: my %courseinfo = &Apache::lonnet::coursedescription($crs); 1365: my $usec = $selfenrollrequests{$crs}{'section'}; 1366: if ($usec eq '') { 1367: $usec = &mt('No section'); 1368: } 1369: $r->print(&Apache::loncommon::start_data_table_row(). 1370: '<td>'.&Apache::lonlocal::locallocaltime($item).'</td>'. 1371: '<td>'.$courseinfo{'description'}.'</td>'. 1372: '<td>'.$rolename.'</td><td>'.$usec.'</td>'. 1373: &Apache::loncommon::end_data_table_row()); 1374: } 1375: } 1376: } 1377: $r->print(&Apache::loncommon::end_data_table()); 1378: } 1379: return; 1380: } 1381: 1382: sub privileges_info { 1383: my ($which) = @_; 1384: my $output; 1385: 1386: $which ||= $env{'request.role'}; 1387: 1388: foreach my $envkey (sort(keys(%env))) { 1389: next if ($envkey!~/^user\.priv\.\Q$which\E\.(.*)/); 1390: 1391: my $where=$1; 1392: my $ttype; 1393: my $twhere; 1394: my (undef,$tdom,$trest,$tsec)=split(m{/},$where); 1395: if ($trest) { 1396: if ($env{'course.'.$tdom.'_'.$trest.'.description'} eq 'ca') { 1397: $ttype='Construction Space'; 1398: $twhere='User: '.$trest.', Domain: '.$tdom; 1399: } else { 1400: $ttype= &Apache::loncommon::course_type($tdom.'_'.$trest); 1401: $twhere=$env{'course.'.$tdom.'_'.$trest.'.description'}; 1402: if ($tsec) { 1403: my $sec_type = 'Section'; 1404: if (exists($env{"user.role.gr.$where"})) { 1405: $sec_type = 'Group'; 1406: } 1407: $twhere.=' ('.$sec_type.': '.$tsec.')'; 1408: } 1409: } 1410: } elsif ($tdom) { 1411: $ttype='Domain'; 1412: $twhere=$tdom; 1413: } else { 1414: $ttype='System'; 1415: $twhere='/'; 1416: } 1417: $output .= "\n<h3>".&mt($ttype).': '.$twhere.'</h3>'."\n<ul>"; 1418: foreach my $priv (sort(split(/:/,$env{$envkey}))) { 1419: next if (!$priv); 1420: 1421: my ($prv,$restr)=split(/\&/,$priv); 1422: my $trestr=''; 1423: if ($restr ne 'F') { 1424: $trestr.=' ('. 1425: join(', ', 1426: map { &Apache::lonnet::plaintext($_) } 1427: (split('',$restr))).') '; 1428: } 1429: $output .= "\n\t". 1430: '<li>'.&Apache::lonnet::plaintext($prv).$trestr.'</li>'; 1431: } 1432: $output .= "\n".'</ul>'; 1433: } 1434: return $output; 1435: } 1436: 1437: sub build_roletext { 1438: my ($trolecode,$tdom,$trest,$tstatus,$tryagain,$advanced,$tremark,$tbg,$trole,$twhere,$tpstart,$tpend,$nochoose,$button,$switchserver,$reinit) = @_; 1439: my ($roletext,$roletext_end); 1440: my $is_dc=($trolecode =~ m/^dc\./); 1441: my $rowspan=($is_dc) ? '' 1442: : ' rowspan="2" '; 1443: 1444: unless ($nochoose) { 1445: my $buttonname=$trolecode; 1446: $buttonname=~s/\W//g; 1447: if (!$button) { 1448: if ($switchserver) { 1449: $roletext.='<td'.$rowspan.' class="'.$tbg.'">' 1450: .'<a href="/adm/switchserver?'.$switchserver.'">' 1451: .&mt('Switch Server') 1452: .'</a></td>'; 1453: } else { 1454: $roletext.=('<td'.$rowspan.' class="'.$tbg.'"> </td>'); 1455: } 1456: } elsif ($tstatus eq 'is') { 1457: $roletext.='<td'.$rowspan.' class="'.$tbg.'">'. 1458: '<input name="'.$buttonname.'" type="button" value="'. 1459: &mt('Select').'" onclick="javascript:enterrole(this.form,\''. 1460: $trolecode."','".$buttonname.'\');" /></td>'; 1461: } elsif ($tryagain) { 1462: $roletext.= 1463: '<td'.$rowspan.' class="'.$tbg.'">'. 1464: '<input name="'.$buttonname.'" type="button" value="'. 1465: &mt('Try Selecting Again').'" onclick="javascript:enterrole(this.form,\''. 1466: $trolecode."','".$buttonname.'\');" /></td>'; 1467: } elsif ($advanced) { 1468: $roletext.= 1469: '<td'.$rowspan.' class="'.$tbg.'">'. 1470: '<input name="'.$buttonname.'" type="button" value="'. 1471: &mt('Re-Initialize').'" onclick="javascript:enterrole(this.form,\''. 1472: $trolecode."','".$buttonname.'\');" /></td>'; 1473: } elsif ($reinit) { 1474: $roletext.= 1475: '<td'.$rowspan.' class="'.$tbg.'">'. 1476: '<input name="'.$buttonname.'" type="button" value="'. 1477: &mt('Re-Select').'" onclick="javascript:enterrole(this.form,\''. 1478: $trolecode."','".$buttonname.'\');" /></td>'; 1479: } else { 1480: $roletext.= 1481: '<td'.$rowspan.' class="'.$tbg.'">'. 1482: '<input name="'.$buttonname.'" type="button" value="'. 1483: &mt('Re-Select').'" onclick="javascript:enterrole(this.form,\''. 1484: $trolecode."','".$buttonname.'\');" /></td>'; 1485: } 1486: } 1487: if ($trolecode !~ m/^(dc|ca|au|aa)\./) { 1488: $tremark.=&Apache::lonannounce::showday(time,1, 1489: &Apache::lonannounce::readcalendar($tdom.'_'.$trest)); 1490: } 1491: $roletext.='<td>'.$trole.'</td>' 1492: .'<td>'.$twhere.'</td>' 1493: .'<td>'.$tpstart.'</td>' 1494: .'<td>'.$tpend.'</td>'; 1495: if (!$is_dc) { 1496: $roletext_end = '<td colspan="4">'. 1497: $tremark.' '. 1498: '</td>'; 1499: } 1500: return ($roletext,$roletext_end); 1501: } 1502: 1503: sub check_needs_switchserver { 1504: my ($possiblerole) = @_; 1505: my $needs_switchserver; 1506: my ($role,$where) = split(/\./,$possiblerole,2); 1507: my (undef,$tdom,$twho) = split(/\//,$where); 1508: my ($server_status,$home); 1509: if (($role eq 'ca') || ($role eq 'aa')) { 1510: ($server_status,$home) = &check_author_homeserver($twho,$tdom); 1511: } else { 1512: ($server_status,$home) = &check_author_homeserver($env{'user.name'}, 1513: $env{'user.domain'}); 1514: } 1515: if ($server_status eq 'switchserver') { 1516: $needs_switchserver = 1; 1517: } 1518: return $needs_switchserver; 1519: } 1520: 1521: sub check_author_homeserver { 1522: my ($uname,$udom)=@_; 1523: if (($uname eq '') || ($udom eq '')) { 1524: return ('fail',''); 1525: } 1526: my $home = &Apache::lonnet::homeserver($uname,$udom); 1527: if (&Apache::lonnet::host_domain($home) ne $udom) { 1528: return ('fail',$home); 1529: } 1530: my @ids=&Apache::lonnet::current_machine_ids(); 1531: if (grep(/^\Q$home\E$/,@ids)) { 1532: return ('ok',$home); 1533: } else { 1534: return ('switchserver',$home); 1535: } 1536: } 1537: 1538: sub check_fordc { 1539: my ($dcroles,$then) = @_; 1540: my $numdc = 0; 1541: if ($env{'user.adv'}) { 1542: foreach my $envkey (sort keys %env) { 1543: if ($envkey=~/^user\.role\.dc\.\/($match_domain)\/$/) { 1544: my $dcdom = $1; 1545: my $livedc = 1; 1546: my ($tstart,$tend)=split(/\./,$env{$envkey}); 1547: if ($tstart && $tstart>$then) { $livedc = 0; } 1548: if ($tend && $tend <$then) { $livedc = 0; } 1549: if ($livedc) { 1550: $$dcroles{$dcdom} = $envkey; 1551: $numdc++; 1552: } 1553: } 1554: } 1555: } 1556: return $numdc; 1557: } 1558: 1559: sub adhoc_course_role { 1560: my ($refresh,$then) = @_; 1561: my ($cdom,$cnum,$crstype); 1562: $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; 1563: $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; 1564: $crstype = &Apache::loncommon::course_type(); 1565: if (&check_forcc($cdom,$cnum,$refresh,$then,$crstype)) { 1566: my $setprivs; 1567: if (!defined($env{'user.role.'.$env{'form.switchrole'}})) { 1568: $setprivs = 1; 1569: } else { 1570: my ($start,$end) = split(/\./,$env{'user.role.'.$env{'form.switchrole'}}); 1571: if (($start && ($start>$refresh || $start == -1)) || 1572: ($end && $end<$then)) { 1573: $setprivs = 1; 1574: } 1575: } 1576: if ($setprivs) { 1577: if ($env{'form.switchrole'} =~ m-^(in|ta|ep|ad|st|cr)([\w/]*)\./\Q$cdom\E/\Q$cnum\E/?(\w*)$-) { 1578: my $role = $1; 1579: my $custom_role = $2; 1580: my $usec = $3; 1581: if ($role eq 'cr') { 1582: if ($custom_role =~ m-^/$match_domain/$match_username/\w+$-) { 1583: $role .= $custom_role; 1584: } else { 1585: return; 1586: } 1587: } 1588: my (%userroles,%newrole,%newgroups,%group_privs); 1589: my %cgroups = 1590: &Apache::lonnet::get_active_groups($env{'user.domain'}, 1591: $env{'user.name'},$cdom,$cnum); 1592: foreach my $group (keys(%cgroups)) { 1593: $group_privs{$group} = 1594: $env{'user.priv.cc./'.$cdom.'/'.$cnum.'./'.$cdom.'/'.$cnum.'/'.$group}; 1595: } 1596: $newgroups{'/'.$cdom.'/'.$cnum} = \%group_privs; 1597: my $area = '/'.$cdom.'/'.$cnum; 1598: my $spec = $role.'.'.$area; 1599: if ($usec ne '') { 1600: $spec .= '/'.$usec; 1601: $area .= '/'.$usec; 1602: } 1603: &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum,$area); 1604: &Apache::lonnet::set_userprivs(\%userroles,\%newrole,\%newgroups); 1605: my $adhocstart = $refresh-1; 1606: $userroles{'user.role.'.$spec} = $adhocstart.'.'; 1607: &Apache::lonnet::appenv(\%userroles,[$role,'cm']); 1608: } 1609: } 1610: } 1611: return; 1612: } 1613: 1614: sub check_forcc { 1615: my ($cdom,$cnum,$refresh,$then,$crstype) = @_; 1616: my ($is_cc,$ccrole); 1617: if ($crstype eq 'Community') { 1618: $ccrole = 'co'; 1619: } else { 1620: $ccrole = 'cc'; 1621: } 1622: if ($cdom ne '' && $cnum ne '') { 1623: if (&Apache::lonnet::is_course($cdom,$cnum)) { 1624: my $envkey = 'user.role.'.$ccrole.'./'.$cdom.'/'.$cnum; 1625: if (defined($env{$envkey})) { 1626: $is_cc = 1; 1627: my ($tstart,$tend)=split(/\./,$env{$envkey}); 1628: if ($tstart && $tstart>$refresh) { $is_cc = 0; } 1629: if ($tend && $tend <$then) { $is_cc = 0; } 1630: } 1631: } 1632: } 1633: return $is_cc; 1634: } 1635: 1636: sub courselink { 1637: my ($dcdom,$rowtype) = @_; 1638: my $courseform=&Apache::loncommon::selectcourse_link 1639: ('rolechoice','dccourse'.$rowtype.'_'.$dcdom, 1640: 'dcdomain'.$rowtype.'_'.$dcdom,'coursedesc'.$rowtype.'_'. 1641: $dcdom,$dcdom,undef,'Course/Community'); 1642: my $hiddenitems = '<input type="hidden" name="dcdomain'.$rowtype.'_'.$dcdom.'" value="'.$dcdom.'" />'. 1643: '<input type="hidden" name="origdom'.$rowtype.'_'.$dcdom.'" value="'.$dcdom.'" />'. 1644: '<input type="hidden" name="dccourse'.$rowtype.'_'.$dcdom.'" value="" />'. 1645: '<input type="hidden" name="coursedesc'.$rowtype.'_'.$dcdom.'" value="" />'; 1646: return $courseform.$hiddenitems; 1647: } 1648: 1649: sub coursepick_jscript { 1650: my %lt = &Apache::lonlocal::texthash( 1651: plsu => "Please use the 'Select Course/Community' link to open a separate pick course window where you may select the course or community you wish to enter.", 1652: youc => 'You can only use this screen to select courses and communities in the current domain.', 1653: ); 1654: my $verify_script = <<"END"; 1655: <script type="text/javascript"> 1656: // <![CDATA[ 1657: function verifyCoursePick(caller) { 1658: var numbutton = getIndex(caller) 1659: var pickedCourse = document.rolechoice.elements[numbutton+4].value 1660: var pickedDomain = document.rolechoice.elements[numbutton+2].value 1661: if (document.rolechoice.elements[numbutton+2].value == document.rolechoice.elements[numbutton+3].value) { 1662: if (pickedCourse != '') { 1663: if (numbutton != -1) { 1664: var courseTarget = "cc./"+pickedDomain+"/"+pickedCourse 1665: document.rolechoice.elements[numbutton+1].name = courseTarget 1666: document.rolechoice.submit() 1667: } 1668: } 1669: else { 1670: alert("$lt{'plsu'}"); 1671: } 1672: } 1673: else { 1674: alert("$lt{'youc'}") 1675: } 1676: } 1677: function getIndex(caller) { 1678: for (var i=0;i<document.rolechoice.elements.length;i++) { 1679: if (document.rolechoice.elements[i] == caller) { 1680: return i; 1681: } 1682: } 1683: return -1; 1684: } 1685: // ]]> 1686: </script> 1687: END 1688: return $verify_script; 1689: } 1690: 1691: sub coauthorlink { 1692: my ($dcdom,$rowtype) = @_; 1693: my $coauthorform=&Apache::loncommon::selectauthor_link('rolechoice',$dcdom); 1694: my $hiddenitems = '<input type="hidden" name="adhoccauname'.$rowtype.'_'.$dcdom.'" value="" />'; 1695: return $coauthorform.$hiddenitems; 1696: } 1697: 1698: sub display_cc_role { 1699: my $rolekey = shift; 1700: my ($roletext,$roletext_end); 1701: my $advanced = $env{'user.adv'}; 1702: my $tryagain = $env{'form.tryagain'}; 1703: unless ($rolekey =~/^error\:/) { 1704: if ($rolekey =~ m{^user\.role\.(cc|co)\./($match_domain)/($match_courseid)$}) { 1705: my $ccrole = $1; 1706: my $tcourseid = $2.'_'.$3; 1707: my $trolecode = $1.'./'.$2.'/'.$3; 1708: my $twhere; 1709: my $ttype; 1710: my $tbg='LC_roles_is'; 1711: my %newhash=&Apache::lonnet::coursedescription($tcourseid); 1712: if (%newhash) { 1713: $twhere=$newhash{'description'}. 1714: ' <span style="LC_fontsize_small">'. 1715: &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$2,$1). 1716: '</span>'; 1717: $ttype = $newhash{'type'}; 1718: } else { 1719: $twhere=&mt('Currently not available'); 1720: $env{'course.'.$tcourseid.'.description'}=$twhere; 1721: } 1722: my $trole = &Apache::lonnet::plaintext($ccrole,$ttype,$tcourseid); 1723: $twhere.="<br />".&mt('Domain').":".$1; 1724: ($roletext,$roletext_end) = &build_roletext($trolecode,$1,$2,'is',$tryagain,$advanced,'',$tbg,$trole,$twhere,'','','',1,''); 1725: } 1726: } 1727: return ($roletext,$roletext_end); 1728: } 1729: 1730: sub adhoc_roles_row { 1731: my ($dcdom,$rowtype) = @_; 1732: my $output = &Apache::loncommon::continue_data_table_row() 1733: .' <td colspan="5">' 1734: .&mt('[_1]Ad hoc[_2] roles in domain [_3] --' 1735: ,'<span class="LC_cusr_emph">','</span>',$dcdom) 1736: .' '; 1737: my $selectcclink = &courselink($dcdom,$rowtype); 1738: my $ccrole = &Apache::lonnet::plaintext('co',undef,undef,1); 1739: my $carole = &Apache::lonnet::plaintext('ca'); 1740: my $selectcalink = &coauthorlink($dcdom,$rowtype); 1741: $output.=$ccrole.': '.$selectcclink 1742: .' | '.$carole.': '.$selectcalink 1743: .&Apache::loncommon::end_data_table_row(); 1744: return $output; 1745: } 1746: 1747: sub recent_filename { 1748: my $area=shift; 1749: return 'nohist_recent_'.&escape($area); 1750: } 1751: 1752: sub courseloadpage { 1753: my ($courseid) = @_; 1754: my $startpage; 1755: my %entry_settings = &Apache::lonnet::get('nohist_whatsnew', 1756: [$courseid.':courseinit']); 1757: my ($tmp) = %entry_settings; 1758: unless ($tmp =~ /^error: 2 /) { 1759: $startpage = $entry_settings{$courseid.':courseinit'}; 1760: } 1761: if ($startpage eq '') { 1762: if (exists($env{'environment.course_init_display'})) { 1763: $startpage = $env{'environment.course_init_display'}; 1764: } 1765: } 1766: return $startpage; 1767: } 1768: 1769: 1; 1770: __END__ 1771: 1772: =head1 NAME 1773: 1774: Apache::lonroles - User Roles Screen 1775: 1776: =head1 SYNOPSIS 1777: 1778: Invoked by /etc/httpd/conf/srm.conf: 1779: 1780: <Location /adm/roles> 1781: PerlAccessHandler Apache::lonacc 1782: SetHandler perl-script 1783: PerlHandler Apache::lonroles 1784: ErrorDocument 403 /adm/login 1785: ErrorDocument 500 /adm/errorhandler 1786: </Location> 1787: 1788: =head1 OVERVIEW 1789: 1790: =head2 Choosing Roles 1791: 1792: C<lonroles> is a handler that allows a user to switch roles in 1793: mid-session. LON-CAPA attempts to work with "No Role Specified", the 1794: default role that a user has before selecting a role, as widely as 1795: possible, but certain handlers for example need specification which 1796: course they should act on, etc. Both in this scenario, and when the 1797: handler determines via C<lonnet>'s C<&allowed> function that a certain 1798: action is not allowed, C<lonroles> is used as error handler. This 1799: allows the user to select another role which may have permission to do 1800: what they were trying to do. C<lonroles> can also be accessed via the 1801: B<CRS> button in the Remote Control. 1802: 1803: =begin latex 1804: 1805: \begin{figure} 1806: \begin{center} 1807: \includegraphics[width=0.45\paperwidth,keepaspectratio]{Sample_Roles_Screen} 1808: \caption{\label{Sample_Roles_Screen}Sample Roles Screen} 1809: \end{center} 1810: \end{figure} 1811: 1812: =end latex 1813: 1814: =head2 Role Initialization 1815: 1816: 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. 1817: 1818: =head1 INTRODUCTION 1819: 1820: This module enables a user to select what role he wishes to 1821: operate under (instructor, student, teaching assistant, course 1822: coordinator, etc). These roles are pre-established by the actions 1823: of upper-level users. 1824: 1825: This is part of the LearningOnline Network with CAPA project 1826: described at http://www.lon-capa.org. 1827: 1828: =head1 HANDLER SUBROUTINE 1829: 1830: This routine is called by Apache and mod_perl. 1831: 1832: =over 4 1833: 1834: =item * 1835: 1836: Roles Initialization (yes/no) 1837: 1838: =item * 1839: 1840: Get Error Message from Environment 1841: 1842: =item * 1843: 1844: Who is this? 1845: 1846: =item * 1847: 1848: Generate Page Output 1849: 1850: =item * 1851: 1852: Choice or no choice 1853: 1854: =item * 1855: 1856: Table 1857: 1858: =item * 1859: 1860: Privileges 1861: 1862: =back 1863: 1864: =cut