--- loncom/auth/lonroles.pm 2000/10/05 19:15:34 1.12
+++ loncom/auth/lonroles.pm 2011/02/24 23:29:10 1.260
@@ -1,300 +1,2580 @@
# The LearningOnline Network with CAPA
# User Roles Screen
-# (Directory Indexer
-# (Login Screen
-# 5/21/99,5/22,5/25,5/26,5/31,6/2,6/10,7/12,7/14 Gerd Kortemeyer)
-# 11/23 Gerd Kortemeyer)
-# 1/14,03/06,06/01,07/22,07/24,07/25,
-# 09/04,09/06,09/28,09/29,09/30,10/2,10/5 Gerd Kortemeyer
#
+# $Id: lonroles.pm,v 1.260 2011/02/24 23:29:10 raeburn Exp $
+#
+# Copyright Michigan State University Board of Trustees
+#
+# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
+#
+# LON-CAPA is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# LON-CAPA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LON-CAPA; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# /home/httpd/html/adm/gpl.txt
+#
+# http://www.lon-capa.org/
+#
+###
+
+=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.
+
+=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;
-use Apache::lonnet();
+use Apache::lonnet;
use Apache::lonuserstate();
use Apache::Constants qw(:common);
use Apache::File();
+use Apache::lonmenu;
+use Apache::loncommon;
+use Apache::lonhtmlcommon;
+use Apache::lonannounce;
+use Apache::lonlocal;
+use Apache::lonpageflip();
+use Apache::lonnavdisplay();
+use Apache::loncoursequeueadmin;
+use GDBM_File;
+use LONCAPA qw(:DEFAULT :match);
+use HTML::Entities;
+
+
+sub redirect_user {
+ my ($r,$title,$url,$msg) = @_;
+ $msg = $title if (! defined($msg));
+ &Apache::loncommon::content_type($r,'text/html');
+ &Apache::loncommon::no_cache($r);
+ $r->send_http_header;
+
+ # Breadcrumbs
+ my $brcrum = [{'href' => $url,
+ 'text' => 'Switching Role'},];
+ my $start_page = &Apache::loncommon::start_page('Switching Role',undef,
+ {'redirect' => [1,$url],
+ 'bread_crumbs' => $brcrum,});
+ my $end_page = &Apache::loncommon::end_page();
+
+# Note to style police:
+# This must only replace the spaces, nothing else, or it bombs elsewhere.
+ $url=~s/ /\%20/g;
+ $r->print(<$msg
+$end_page
+ENDREDIR
+ return;
+}
+
+sub error_page {
+ my ($r,$error,$dest)=@_;
+ &Apache::loncommon::content_type($r,'text/html');
+ &Apache::loncommon::no_cache($r);
+ $r->send_http_header;
+ return OK if $r->header_only;
+ # 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('Continue').''
+ );
+ $r->print(&Apache::loncommon::end_page());
+}
sub handler {
my $r = shift;
my $now=time;
- my $then=$ENV{'user.login.time'};
- my $envkey;
+ my $then=$env{'user.login.time'};
+ my $refresh=$env{'user.refresh.time'};
+ my $update=$env{'user.update.time'};
+ if (!$refresh) {
+ $refresh = $then;
+ }
+ if (!$update) {
+ $update = $then;
+ }
+
+# -------------------------------------------------------- Check for new roles
+ my $updateresult;
+ if ($env{'form.doupdate'}) {
+ my $show_course=&Apache::loncommon::show_course();
+ my $checkingtxt;
+ if ($show_course) {
+ $checkingtxt = &mt('Checking for new courses ...');
+ } else {
+ $checkingtxt = &mt('Checking for new roles ...');
+ }
+ $updateresult = '
'.$checkingtxt.'
';
+ $updateresult .= &update_session_roles();
+ &Apache::lonnet::appenv({'user.update.time' => $now});
+ $update = $now;
+ }
+ my $envkey;
+ my %dcroles = ();
+ my $numdc = &check_fordc(\%dcroles,$update,$then);
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
+ my $loncaparev = $Apache::lonnet::perlvar{'lonVersion'};
# ================================================================== Roles Init
+ if ($env{'form.selectrole'}) {
- if ($ENV{'form.selectrole'}) {
- foreach $envkey (keys %ENV) {
- if ($envkey=~/^user\.role\./) {
- my ($dum1,$dum2,$role,@pwhere)=split(/\./,$envkey);
- my $where=join('.',@pwhere);
- my $trolecode=$role.'.'.$where;
- if ($ENV{'form.'.$trolecode}) {
- my ($tstart,$tend)=split(/\./,$ENV{$envkey});
- my $tstatus='is';
- if ($tstart) {
- if ($tstart>$then) {
- $tstatus='future';
- }
- }
- if ($tend) {
- if ($tend<$then) { $tstatus='expired'; }
- if ($tend>$now) { $tstatus='will_not'; }
- }
- if ($tstatus eq 'is') {
- &Apache::lonnet::appenv('request.role' => $trolecode);
- my ($cdom,$cnum)=split(/\//,$where);
- if ($cnum) {
- &Apache::lonuserstate::readmap($where);
- if ($ENV{'form.orgurl'}) {
- $r->internal_redirect($ENV{'form.orgurl'});
- return OK;
- }
- }
- }
- }
- }
+ my $locknum=&Apache::lonnet::get_locks();
+ if ($locknum) { return 409; }
+
+ if ($env{'form.newrole'}) {
+ $env{'form.'.$env{'form.newrole'}}=1;
+ }
+ if ($env{'request.course.id'}) {
+ # Check if user is CC trying to select a course role
+ if ($env{'form.switchrole'}) {
+ my $switch_is_active;
+ if (defined($env{'user.role.'.$env{'form.switchrole'}})) {
+ my ($start,$end) = split(/\./,$env{'user.role.'.$env{'form.switchrole'}});
+ if (!$end || $end > $now) {
+ if (!$start || $start < $update) {
+ $switch_is_active = 1;
+ }
+ }
+ }
+ unless ($switch_is_active) {
+ &adhoc_course_role($refresh,$update,$then);
+ }
+ }
+ my %temp=('logout_'.$env{'request.course.id'} => time);
+ &Apache::lonnet::put('email_status',\%temp);
+ &Apache::lonnet::delenv('user.state.'.$env{'request.course.id'});
+ }
+ &Apache::lonnet::appenv({"request.course.id" => '',
+ "request.course.fn" => '',
+ "request.course.uri" => '',
+ "request.course.sec" => '',
+ "request.role" => 'cm',
+ "request.role.adv" => $env{'user.adv'},
+ "request.role.domain" => $env{'user.domain'}});
+# Check if user is a DC trying to enter a course or author space and needs privs to be created
+ if ($numdc > 0) {
+ foreach my $envkey (keys %env) {
+# Is this an ad-hoc Coordinator role?
+ if (my ($ccrole,$domain,$coursenum) =
+ ($envkey =~ m-^form\.(cc|co)\./($match_domain)/($match_courseid)$-)) {
+ if ($dcroles{$domain}) {
+ &Apache::lonnet::check_adhoc_privs($domain,$coursenum,
+ $update,$refresh,$now,$ccrole);
+ }
+ last;
+ }
+# Is this an ad-hoc CA-role?
+ if (my ($domain,$user) =
+ ($envkey =~ m-^form\.ca\./($match_domain)/($match_username)$-)) {
+ if (($domain eq $env{'user.domain'}) && ($user eq $env{'user.name'})) {
+ delete($env{$envkey});
+ $env{'form.au./'.$domain.'/'} = 1;
+ my ($server_status,$home) = &check_author_homeserver($user,$domain);
+ if ($server_status eq 'switchserver') {
+ my $trolecode = 'au./'.$domain.'/';
+ my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode;
+ $r->internal_redirect($switchserver);
+ }
+ last;
+ }
+ if (my ($castart,$caend) = ($env{'user.role.ca./'.$domain.'/'.$user} =~ /^(\d*)\.(\d*)$/)) {
+ if (((($castart) && ($castart < $now)) || !$castart) &&
+ ((!$caend) || (($caend) && ($caend > $now)))) {
+ my ($server_status,$home) = &check_author_homeserver($user,$domain);
+ if ($server_status eq 'switchserver') {
+ my $trolecode = 'ca./'.$domain.'/'.$user;
+ my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode;
+ $r->internal_redirect($switchserver);
+ }
+ last;
+ }
+ }
+ # Check if author blocked ca-access
+ my %blocked=&Apache::lonnet::get('environment',['domcoord.author'],$domain,$user);
+ if ($blocked{'domcoord.author'} eq 'blocked') {
+ delete($env{$envkey});
+ $env{'user.error.msg'}=':::1:User '.$user.' in domain '.$domain.' blocked domain coordinator access';
+ last;
+ }
+ if ($dcroles{$domain}) {
+ my ($server_status,$home) = &check_author_homeserver($user,$domain);
+ if (($server_status eq 'ok') || ($server_status eq 'switchserver')) {
+ &Apache::lonnet::check_adhoc_privs($domain,$user,$update,
+ $refresh,$now,'ca');
+ if ($server_status eq 'switchserver') {
+ my $trolecode = 'ca./'.$domain.'/'.$user;
+ my $switchserver = '/adm/switchserver?'
+ .'otherserver='.$home.'&role='.$trolecode;
+ $r->internal_redirect($switchserver);
+ }
+ } else {
+ delete($env{$envkey});
+ }
+ } else {
+ delete($env{$envkey});
+ }
+ last;
+ }
+ }
+ }
+
+ foreach $envkey (keys %env) {
+ next if ($envkey!~/^user\.role\./);
+ my ($where,$trolecode,$role,$tstatus,$tend,$tstart);
+ &Apache::lonnet::role_status($envkey,$update,$refresh,$now,\$role,\$where,
+ \$trolecode,\$tstatus,\$tstart,\$tend);
+ if ($env{'form.'.$trolecode}) {
+ if ($tstatus eq 'is') {
+ $where=~s/^\///;
+ my ($cdom,$cnum,$csec)=split(/\//,$where);
+ if (($cnum) && ($role ne 'ca') && ($role ne 'aa')) {
+ my $home = $env{'course.'.$cdom.'_'.$cnum.'.home'};
+ my @ids = &Apache::lonnet::current_machine_ids();
+ unless ($loncaparev eq '' && $home && grep(/^\Q$home\E$/,@ids)) {
+ my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');
+ if ($curr_reqd_hash{'internal.releaserequired'} ne '') {
+ my ($switchserver,$switchwarning) =
+ &check_release_required($loncaparev,$cdom.'_'.$cnum,$trolecode,$curr_reqd_hash{'internal.releaserequired'});
+ if ($switchwarning ne '' || $switchserver ne '') {
+ &Apache::loncommon::content_type($r,'text/html');
+ &Apache::loncommon::no_cache($r);
+ $r->send_http_header;
+ my $end_page=&Apache::loncommon::end_page();
+ $r->print(&Apache::loncommon::start_page('Selected course unavailable on this server').
+ '