--- loncom/auth/lonroles.pm 2008/10/08 03:37:20 1.208
+++ loncom/auth/lonroles.pm 2009/07/24 02:00:28 1.230
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# User Roles Screen
#
-# $Id: lonroles.pm,v 1.208 2008/10/08 03:37:20 raeburn Exp $
+# $Id: lonroles.pm,v 1.230 2009/07/24 02:00:28 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -27,6 +27,103 @@
#
###
+=pod
+
+=head1 NAME
+
+Apache::lonroles - User Roles Screen
+
+=head1 SYNOPSIS
+
+Invoked by /etc/httpd/conf/srm.conf:
+
+
+ PerlAccessHandler Apache::lonacc
+ SetHandler perl-script
+ PerlHandler Apache::lonroles
+ ErrorDocument 403 /adm/login
+ ErrorDocument 500 /adm/errorhandler
+
+
+=head1 OVERVIEW
+
+=head2 Choosing Roles
+
+C is a handler that allows a user to switch roles in
+mid-session. LON-CAPA attempts to work with "No Role Specified", the
+default role that a user has before selecting a role, as widely as
+possible, but certain handlers for example need specification which
+course they should act on, etc. Both in this scenario, and when the
+handler determines via C's C<&allowed> function that a certain
+action is not allowed, C is used as error handler. This
+allows the user to select another role which may have permission to do
+what they were trying to do. C can also be accessed via the
+B button in the Remote Control.
+
+=begin latex
+
+\begin{figure}
+\begin{center}
+\includegraphics[width=0.45\paperwidth,keepaspectratio]{Sample_Roles_Screen}
+ \caption{\label{Sample_Roles_Screen}Sample Roles Screen}
+\end{center}
+\end{figure}
+
+=end latex
+
+=head2 Role Initialization
+
+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'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.
+
+=head1 INTRODUCTION
+
+This module enables a user to select what role he wishes to
+operate under (instructor, student, teaching assistant, course
+coordinator, etc). These roles are pre-established by the actions
+of upper-level users.
+
+This is part of the LearningOnline Network with CAPA project
+described at http://www.lon-capa.org.
+
+=head1 HANDLER SUBROUTINE
+
+This routine is called by Apache and mod_perl.
+
+=over 4
+
+=item *
+
+Roles Initialization (yes/no)
+
+=item *
+
+Get Error Message from Environment
+
+=item *
+
+Who is this?
+
+=item *
+
+Generate Page Output
+
+=item *
+
+Choice or no choice
+
+=item *
+
+Table
+
+=item *
+
+Privileges
+
+=back
+
+=cut
+
+
package Apache::lonroles;
use strict;
@@ -60,8 +157,13 @@ sub redirect_user {
} else {
$navwindow.=&Apache::lonnavmaps::close();
}
+
+ # Breadcrumbs
+ my $brcrum = [{'href' => $url,
+ 'text' => 'Switching Role'},];
my $start_page = &Apache::loncommon::start_page('Switching Role',undef,
- {'redirect' => [1,$url],});
+ {'redirect' => [1,$url],
+ 'bread_crumbs' => $brcrum,});
my $end_page = &Apache::loncommon::end_page();
# Note to style police:
@@ -70,10 +172,12 @@ sub redirect_user {
$r->print(<
+//
$navwindow
-$msg
+$msg
$end_page
ENDREDIR
return;
@@ -85,13 +189,25 @@ sub error_page {
&Apache::loncommon::no_cache($r);
$r->send_http_header;
return OK if $r->header_only;
- $r->print(&Apache::loncommon::start_page('Problems during Course Initialization').
- ''.
- ''.&mt('The following problems occurred:').
+ # Breadcrumbs
+ my $brcrum = [{'href' => $dest,
+ 'text' => 'Problems during Course Initialization'},];
+ $r->print(&Apache::loncommon::start_page('Problems during Course Initialization',
+ undef,
+ {'bread_crumbs' => $brcrum,})
+ );
+ $r->print(
+ ''.
+ '
'.&mt('The following problems occurred:').
+ '
'.
$error.
- '
'.&mt('Continue').''.
- &Apache::loncommon::end_page());
+ '
'.&mt('Continue').''
+ );
+ $r->print(&Apache::loncommon::end_page());
}
sub handler {
@@ -100,6 +216,10 @@ sub handler {
my $now=time;
my $then=$env{'user.login.time'};
+ my $refresh=$env{'user.refresh.time'};
+ if (!$refresh) {
+ $refresh = $then;
+ }
my $envkey;
my %dcroles = ();
my $numdc = &check_fordc(\%dcroles,$then);
@@ -139,7 +259,8 @@ sub handler {
if (my ($domain,$coursenum) =
($envkey =~ m-^form\.cc\./($match_domain)/($match_courseid)$-)) {
if ($dcroles{$domain}) {
- &check_privs($domain,$coursenum,$then,$now,'cc');
+ &Apache::lonnet::check_adhoc_privs($domain,$coursenum,
+ $then,$refresh,$now,'cc');
}
last;
}
@@ -179,7 +300,8 @@ sub handler {
if ($dcroles{$domain}) {
my ($server_status,$home) = &check_author_homeserver($user,$domain);
if (($server_status eq 'ok') || ($server_status eq 'switchserver')) {
- &check_privs($domain,$user,$then,$now,'ca');
+ &Apache::lonnet::check_adhoc_privs($domain,$user,$then,
+ $refresh,$now,'ca');
if ($server_status eq 'switchserver') {
my $trolecode = 'ca./'.$domain.'/'.$user;
my $switchserver = '/adm/switchserver?'
@@ -200,7 +322,8 @@ sub handler {
foreach $envkey (keys %env) {
next if ($envkey!~/^user\.role\./);
my ($where,$trolecode,$role,$tstatus,$tend,$tstart);
- &role_status($envkey,$then,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend);
+ &Apache::lonnet::role_status($envkey,$then,$refresh,$now,\$role,\$where,
+ \$trolecode,\$tstatus,\$tstart,\$tend);
if ($env{'form.'.$trolecode}) {
if ($tstatus eq 'is') {
$where=~s/^\///;
@@ -267,12 +390,14 @@ sub handler {
$r->print(<
+//
-
$end_page
@@ -290,9 +415,11 @@ ENDENTEREDKEY
$r->print(<
+//
-\n");
}
# ------------------------------------------------------------ Privileges Info
if (($advanced) && (($env{'user.error.msg'}) || ($error))) {
- $r->print('
Current Privileges
');
+ $r->print('
'.&mt('Current Privileges').'
');
$r->print(&privileges_info());
}
$r->print(&Apache::lonnet::getannounce());
@@ -819,21 +849,236 @@ ENDHEADER
.''.&mt('Logout').' '
.''
.&mt('Course Catalog')
- .'');
+ .'');
}
$r->print(&Apache::loncommon::end_page());
return OK;
}
+sub gather_roles {
+ my ($then,$refresh,$now,$reinit,$nochoose,$roletext,$sortrole,$roleclass,$futureroles,$timezones) = @_;
+ my ($countactive,$countfuture,$inrole,$possiblerole) = (0,0,0,'');
+ my $advanced = $env{'user.adv'};
+ my $tryagain = $env{'form.tryagain'};
+ foreach my $envkey (sort(keys(%env))) {
+ my $button = 1;
+ my $switchserver='';
+ my ($role_text,$role_text_end,$sortkey);
+ if ($envkey=~/^user\.role\./) {
+ my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend);
+ &Apache::lonnet::role_status($envkey,$then,$refresh,$now,\$role,\$where,
+ \$trolecode,\$tstatus,\$tstart,\$tend);
+ next if (!defined($role) || $role eq '' || $role =~ /^gr/);
+ my $timezone = &role_timezone($where,$timezones);
+ $tremark='';
+ $tpstart=' ';
+ $tpend=' ';
+ if ($tstart) {
+ $tpstart=&Apache::lonlocal::locallocaltime($tstart,$timezone);
+ }
+ if ($tend) {
+ $tpend=&Apache::lonlocal::locallocaltime($tend,$timezone);
+ }
+ if ($env{'request.role'} eq $trolecode) {
+ $tstatus='selected';
+ }
+ my $tbg;
+ if (($tstatus eq 'is')
+ || ($tstatus eq 'selected')
+ || ($tstatus eq 'future')
+ || ($env{'form.showall'})) {
+ if ($tstatus eq 'is') {
+ $tbg='LC_roles_is';
+ $possiblerole=$trolecode;
+ $countactive++;
+ } elsif ($tstatus eq 'future') {
+ $tbg='LC_roles_future';
+ $button=0;
+ $futureroles->{$trolecode} = $tstart.':'.$tend;
+ $countfuture ++;
+ } elsif ($tstatus eq 'expired') {
+ $tbg='LC_roles_expired';
+ $button=0;
+ } elsif ($tstatus eq 'will_not') {
+ $tbg='LC_roles_will_not';
+ $tremark.=&mt('Expired after logout.').' ';
+ } elsif ($tstatus eq 'selected') {
+ $tbg='LC_roles_selected';
+ $inrole=1;
+ $countactive++;
+ $tremark.=&mt('Currently selected.').' ';
+ }
+ my $trole;
+ if ($role =~ /^cr\//) {
+ my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$role);
+ if ($tremark) { $tremark.='
'; }
+ $tremark.=&mt('Defined by [_1] at [_2].',$rauthor,$rdomain);
+ }
+ $trole=Apache::lonnet::plaintext($role);
+ my $ttype;
+ my $twhere;
+ my ($tdom,$trest,$tsection)=
+ split(/\//,Apache::lonnet::declutter($where));
+ # First, Co-Authorship roles
+ if (($role eq 'ca') || ($role eq 'aa')) {
+ my $home = &Apache::lonnet::homeserver($trest,$tdom);
+ my $allowed=0;
+ my @ids=&Apache::lonnet::current_machine_ids();
+ foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
+ if (!$allowed) {
+ $button=0;
+ $switchserver='otherserver='.$home.'&role='.$trolecode;
+ }
+ #next if ($home eq 'no_host');
+ $home = &Apache::lonnet::hostname($home);
+ $ttype='Construction Space';
+ $twhere=&mt('User').': '.$trest.'
'.&mt('Domain').
+ ': '.$tdom.'
'.
+ ' '.&mt('Server').': '.$home;
+ $env{'course.'.$tdom.'_'.$trest.'.description'}='ca';
+ $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$trest.'/');
+ $sortkey=$role."$trest:$tdom";
+ } elsif ($role eq 'au') {
+ # Authors
+ my $home = &Apache::lonnet::homeserver
+ ($env{'user.name'},$env{'user.domain'});
+ my $allowed=0;
+ my @ids=&Apache::lonnet::current_machine_ids();
+ foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
+ if (!$allowed) {
+ $button=0;
+ $switchserver='otherserver='.$home.'&role='.$trolecode;
+ }
+ #next if ($home eq 'no_host');
+ $home = &Apache::lonnet::hostname($home);
+ $ttype='Construction Space';
+ $twhere=&mt('Domain').': '.$tdom.'
'.&mt('Server').
+ ': '.$home;
+ $env{'course.'.$tdom.'_'.$trest.'.description'}='ca';
+ $tremark.=&Apache::lonhtmlcommon::authorbombs('/res/'.$tdom.'/'.$env{'user.name'}.'/');
+ $sortkey=$role;
+ } elsif ($trest) {
+ my $tcourseid=$tdom.'_'.$trest;
+ $ttype = &Apache::loncommon::course_type($tcourseid);
+ $trole = &Apache::lonnet::plaintext($role,$ttype);
+ if ($env{'course.'.$tcourseid.'.description'}) {
+ $twhere=$env{'course.'.$tcourseid.'.description'};
+ $sortkey=$role."\0".$tdom."\0".$twhere."\0".$envkey;
+ unless ($twhere eq &mt('Currently not available')) {
+ $twhere.=' '.
+ &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom).
+ '';
+ }
+ } else {
+ my %newhash=&Apache::lonnet::coursedescription($tcourseid);
+ if (%newhash) {
+ $sortkey=$role."\0".$tdom."\0".$newhash{'description'}.
+ "\0".$envkey;
+ $twhere=$newhash{'description'}.
+ ' '.
+ &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom).
+ '';
+ $ttype = $newhash{'type'};
+ $trole = &Apache::lonnet::plaintext($role,$ttype);
+ } else {
+ $twhere=&mt('Currently not available');
+ $env{'course.'.$tcourseid.'.description'}=$twhere;
+ $sortkey=$role."\0".$tdom."\0".$twhere."\0".$envkey;
+ $ttype = 'Unavailable';
+ }
+ }
+ if ($tsection) {
+ $twhere.='
'.&mt('Section').': '.$tsection;
+ }
+ if ($role ne 'st') { $twhere.="
".&mt('Domain').":".$tdom; }
+ } elsif ($tdom) {
+ $ttype='Domain';
+ $twhere=$tdom;
+ $sortkey=$role.$twhere;
+ } else {
+ $ttype='System';
+ $twhere=&mt('system wide');
+ $sortkey=$role.$twhere;
+ }
+ ($role_text,$role_text_end) =
+ &build_roletext($trolecode,$tdom,$trest,$tstatus,$tryagain,
+ $advanced,$tremark,$tbg,$trole,$twhere,$tpstart,
+ $tpend,$nochoose,$button,$switchserver,$reinit);
+ $roletext->{$envkey}=[$role_text,$role_text_end];
+ if (!$sortkey) {$sortkey=$twhere."\0".$envkey;}
+ $sortrole->{$sortkey}=$envkey;
+ $roleclass->{$envkey}=$ttype;
+ }
+ }
+ }
+ return ($countactive,$countfuture,$inrole,$possiblerole);
+}
+
+sub role_timezone {
+ my ($where,$timezones) = @_;
+ my $timezone;
+ if (ref($timezones) eq 'HASH') {
+ if ($where =~ m{^/($match_domain)/($match_courseid)}) {
+ my $cdom = $1;
+ my $cnum = $2;
+ if ($cdom && $cnum) {
+ if (!exists($timezones->{$cdom.'_'.$cnum})) {
+ my %timehash =
+ &Apache::lonnet::get('environment',['timezone'],$cdom,$cnum);
+ if ($timehash{'timezone'} eq '') {
+ if (!exists($timezones->{$cdom})) {
+ my %domdefaults =
+ &Apache::lonnet::get_domain_defaults($cdom);
+ if ($domdefaults{'timezone_def'} eq '') {
+ $timezones->{$cdom} = 'local';
+ } else {
+ $timezones->{$cdom} = $domdefaults{'timezone_def'};
+ }
+ }
+ $timezones->{$cdom.'_'.$cnum} = $timezones->{$cdom};
+ } else {
+ $timezones->{$cdom.'_'.$cnum} =
+ &Apache::lonlocal::gettimezone($timehash{'timezone'});
+ }
+ }
+ $timezone = $timezones->{$cdom.'_'.$cnum};
+ }
+ } else {
+ my ($tdom) = ($where =~ m{^/($match_domain)});
+ if ($tdom) {
+ if (!exists($timezones->{$tdom})) {
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($tdom);
+ if ($domdefaults{'timezone_def'} eq '') {
+ $timezones->{$tdom} = 'local';
+ } else {
+ $timezones->{$tdom} = $domdefaults{'timezone_def'};
+ }
+ }
+ $timezone = $timezones->{$tdom};
+ }
+ }
+ if ($timezone eq 'local') {
+ $timezone = undef;
+ }
+ }
+ return $timezone;
+}
+
sub roletable_headers {
my ($r,$roleclass,$sortrole,$nochoose) = @_;
my $doheaders;
if ((ref($sortrole) eq 'HASH') && (ref($roleclass) eq 'HASH')) {
- $r->print('