[LON-CAPA-cvs] cvs: modules /msu/sentinel sentinel.conf_frag sentinelonly.pm loncom/auth lonacc.pm loncom/interface coursecatalog.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Mon, 08 Jan 2007 15:56:32 -0000


Index: loncom/auth/lonacc.pm
diff -u loncom/auth/lonacc.pm:1.103 loncom/auth/lonacc.pm:1.104
--- loncom/auth/lonacc.pm:1.103	Mon Dec 11 09:06:04 2006
+++ loncom/auth/lonacc.pm	Mon Jan  8 10:54:23 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Cookie Based Access Handler
 #
-# $Id: lonacc.pm,v 1.103 2006/12/11 14:06:04 raeburn Exp $
+# $Id: lonacc.pm,v 1.104 2007/01/08 15:54:23 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -184,6 +184,8 @@
 	}
 	return OK;
     } elsif (defined($r->dir_config('lonSSOUserUnknownRedirect'))) {
+        $r->subprocess_env->set('SSOUserUnknown' => $user);
+        $r->subprocess_env->set('SSOUserDomain' => $domain);
 	$r->internal_redirect($r->dir_config('lonSSOUserUnknownRedirect'));
 	$r->set_handlers('PerlHandler'=> undef);
 	return OK;
Index: loncom/interface/coursecatalog.pm
diff -u loncom/interface/coursecatalog.pm:1.14 loncom/interface/coursecatalog.pm:1.15
--- loncom/interface/coursecatalog.pm:1.14	Sat Jan  6 15:12:19 2007
+++ loncom/interface/coursecatalog.pm	Mon Jan  8 10:54:56 2007
@@ -365,6 +365,7 @@
     my ($domain) = @_;
     my $output;
     my %courses;
+    my $knownuser = &user_is_known();
     if ($env{'form.coursenum'} ne '') {
         %courses = &Apache::lonnet::courseiddump($domain,'.',1,'.','.',
                                                  $env{'form.coursenum'},
@@ -379,19 +380,29 @@
             $output = &mt('No courses match the criteria you selected.');
             return $output;
         }
-        if (&user_is_known()) {
+        if ($knownuser) {
             $output = &mt('<b>Note for students:</b> If you are officially enrolled in a course but the course is not listed in your LON-CAPA courses, click the "Show more details" link for the specific course and check the default access dates and/or automated enrollment settings.<br /><br />');
         }
     }
-    $output .= &Apache::loncommon::start_data_table().
-               &Apache::loncommon::start_data_table_header_row();
-    my @coltitles = ('Code','Sections','Crosslisted','Title','Owner');
+    $output .= &construct_data_table($knownuser,\%courses,$env{'form.coursenum'});
+    $output .= &Apache::lonhtmlcommon::echo_form_input(['coursenum','state','catalogfilter','sortby']);
+    return $output;
+}
+
+sub construct_data_table {
+    my ($knownuser,$courses,$details,$usersections) = @_;
     my %sortname;
-    if ($env{'form.coursenum'} eq '') {
+    if ($details eq '') {
         $sortname{'Code'} = 'code';
         $sortname{'Title'} = 'title';
         $sortname{'Owner'} = 'owner';
     }
+    my $output = &Apache::loncommon::start_data_table().
+                 &Apache::loncommon::start_data_table_header_row();
+    my @coltitles = ('Code','Sections','Crosslisted','Title','Owner');
+    if (ref($usersections) eq 'HASH') {
+       $coltitles[1] = 'Your Section';
+    }
     foreach my $item (@coltitles) {
         $output .= '<th>';
         if (defined($sortname{$item})) {
@@ -401,20 +412,21 @@
         }
         $output .= '</th>';
     }
-    if (&user_is_known()) {
-        if ($env{'form.coursenum'} eq '') {
-            $output .= '<th>&nbsp;</th>';
-        } else {
+    if ($knownuser) {
+        if ($details) {
             $output .=
               '<th>'.&mt('Default Access Dates for Students').'</th>'.
               '<th>'.&mt('Student Counts').'</th>'.
               '<th>'.&mt('Auto-enrollment of <br />registered students').'</th>';
+        } else {
+            $output .= '<th>&nbsp;</th>';
         }
     }
     &Apache::loncommon::end_data_table_header_row();
-    my %courseinfo = &build_courseinfo_hash(%courses);
+    my %courseinfo = &build_courseinfo_hash($courses,$knownuser,$details,
+                                            $usersections);
     my %Sortby;
-    foreach my $course (sort(keys(%courses))) {
+    foreach my $course (sort(keys(%{$courses}))) {
         if ($env{'form.sortby'} eq 'code') {
             push(@{$Sortby{$courseinfo{$course}{'code'}}},$course);
         } elsif ($env{'form.sortby'} eq 'owner') {
@@ -432,33 +444,31 @@
     foreach my $item (@sorted_courses) {
         foreach my $course (@{$Sortby{$item}}) {
             $output.=&Apache::loncommon::start_data_table_row(); 
-            $output.=&courseinfo_row($courseinfo{$course});
+            $output.=&courseinfo_row($courseinfo{$course},$knownuser,$details);
             $output.=&Apache::loncommon::end_data_table_row();
         }
     }
     $output .= &Apache::loncommon::end_data_table();
-    my $echo = &Apache::lonhtmlcommon::echo_form_input(['coursenum','state','catalogfilter','sortby']);
-    $output .= $echo;
     return $output;
 }
 
 sub build_courseinfo_hash {
-    my (%courses) = @_;
+    my ($courses,$knownuser,$details,$usersections) = @_;
     my %courseinfo;
     my $now = time;
-    foreach my $course (keys(%courses)) {
+    foreach my $course (keys(%{$courses})) {
         my $descr;
-        if ($courses{$course} =~ m/^([^:]*):/i) {
+        if ($courses->{$course} =~ m/^([^:]*):/i) {
             $descr = &unescape($1);
         } else {
-            $descr = &unescape($courses{$course});
+            $descr = &unescape($courses->{$course});
         }
         my $cleandesc=&HTML::Entities::encode($descr,'<>&"');
         $cleandesc=~s/'/\\'/g;
         $cleandesc =~ s/^\s+//;
         my ($cdom,$cnum)=split(/\_/,$course);
 
-        my ($desc,$instcode,$owner,$ttype) = split(/:/,$courses{$course});
+        my ($desc,$instcode,$owner,$ttype) = split(/:/,$courses->{$course});
         $owner = &unescape($owner);
         my ($ownername,$ownerdom);
         if ($owner =~ /:/) {
@@ -483,41 +493,47 @@
         my %coursehash = &Apache::lonnet::dump('environment',$cdom,$cnum);
         my @classids;
         my @crosslistings;
-        my $seclist = &identify_sections($coursehash{'internal.sectionnums'});
+        my ($seclist,$numsec) = 
+            &identify_sections($coursehash{'internal.sectionnums'});
+        if (ref($usersections) eq 'HASH') {
+            if (ref($usersections->{$course}) eq 'ARRAY') {
+                $seclist = join(', ',@{$usersections->{$course}});
+            }
+        }
         $courseinfo{$course}{'seclist'} = $seclist;
-        my $xlist_items = &identify_sections($coursehash{'internal.crosslistings'});
+        my ($xlist_items,$numxlist) = 
+            &identify_sections($coursehash{'internal.crosslistings'});
         my $showsyllabus = 1; # default is to include a syllabus link
         if (defined($coursehash{'showsyllabus'})) {
             $showsyllabus = $coursehash{'showsyllabus'};
         }
         $courseinfo{$course}{'showsyllabus'} = $showsyllabus;
-        if (defined($env{'form.coursenum'})) {
-            if ($cnum eq $env{'form.coursenum'}) {
-                $courseinfo{$course}{'counts'} =  &count_students($cdom,$cnum);
-                $courseinfo{$course}{'autoenrollment'} =
-                   &autoenroll_info(\%coursehash,$now,$seclist,$xlist_items,
-                                    $instcode,$owner,$cdom,$cnum);
-
-               my $startaccess = '';
-               my $endaccess = '';
-               my $accessdates;
-               if ( defined($coursehash{'default_enrollment_start_date'}) ) {
-                   $startaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_start_date'});
-               }
-               if ( defined($coursehash{'default_enrollment_end_date'}) ) {
-                   $endaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_end_date'});
-                   if ($coursehash{'default_enrollment_end_date'} == 0) {
-                       $endaccess = "No ending date";
-                   }
-               }
-               if ($startaccess) {
-                   $accessdates .= &mt('<i>From:</i> ').$startaccess.'<br />';
-               }
-               if ($endaccess) {
-                   $accessdates .= &mt('<i>To:</i> ').$endaccess.'<br />';
-               }
-               $courseinfo{$course}{'access'} = $accessdates;
+        if (((defined($env{'form.coursenum'}) && ($cnum eq $env{'form.coursenum'}))) ||
+            ($knownuser && ($details == 1))) {  
+            $courseinfo{$course}{'counts'} =  &count_students($cdom,$cnum,$numsec);
+            $courseinfo{$course}{'autoenrollment'} =
+                &autoenroll_info(\%coursehash,$now,$seclist,$xlist_items,
+                                 $instcode,$owner,$cdom,$cnum);
+
+            my $startaccess = '';
+            my $endaccess = '';
+            my $accessdates;
+            if ( defined($coursehash{'default_enrollment_start_date'}) ) {
+                $startaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_start_date'});
+            }
+            if ( defined($coursehash{'default_enrollment_end_date'}) ) {
+                $endaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_end_date'});
+                if ($coursehash{'default_enrollment_end_date'} == 0) {
+                    $endaccess = "No ending date";
+                }
+            }
+            if ($startaccess) {
+                $accessdates .= &mt('<i>From:</i> ').$startaccess.'<br />';
             }
+            if ($endaccess) {
+                $accessdates .= &mt('<i>To:</i> ').$endaccess.'<br />';
+            }
+            $courseinfo{$course}{'access'} = $accessdates;
         }
         if ($xlist_items eq '') {
             $xlist_items = &mt('No');
@@ -528,7 +544,7 @@
 }
 
 sub count_students {
-    my ($cdom,$cnum) = @_;
+    my ($cdom,$cnum,$numsec) = @_;
     my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cnum);
     my %student_count = (
                            Active => 0,
@@ -547,7 +563,7 @@
         $student_count{$data->[$idx{'status'}]} ++;
     }
 
-    my $countslist;
+    my $countslist = &mt('[quant,_1,section]',$numsec).':<br />';
     foreach my $status ('Active','Future') {
         $countslist .= '<nobr>'.$status_title{$status}.': '.
                        $student_count{$status}.'</nobr><br />';
@@ -556,7 +572,7 @@
 }
 
 sub courseinfo_row {
-    my ($info) = @_;
+    my ($info,$knownuser,$details) = @_;
     my ($cdom,$cnum,$title,$ownerlast,$code,$owner,$seclist,$xlist_items,
         $accessdates,$showsyllabus,$counts,$autoenrollment,$output);
     if (ref($info) eq 'HASH') {
@@ -588,14 +604,14 @@
     }
     $output .= '</font></td>'.
                '<td>'.$ownerlast.'</td>';
-    if (&user_is_known()) {
-        if ($env{'form.coursenum'} eq '') {
-            $output .= "<td><a href=\"javascript:setCourseId('$cnum')\">".&mt('Show more details').'</a></td>';
-        } else { 
+    if ($knownuser) {
+        if ($details) {
             $output .=
                '<td>'.$accessdates.'</td>'. 
                '<td>'.$counts.'</td>'.
                '<td>'.$autoenrollment.'</td>';
+        } else {
+            $output .= "<td><a href=\"javascript:setCourseId('$cnum')\">".&mt('Show more details').'</a></td>';
         }
     }
     return $output;
@@ -620,7 +636,8 @@
     }
     @secnums = sort {$a <=> $b} @secnums;
     my $seclist = join(', ',@secnums);
-    return $seclist;
+    my $numsec = @secnums;
+    return ($seclist,$numsec);
 }
 
 sub get_valid_classes {

Index: modules/msu/sentinel/sentinelonly.pm
+++ modules/msu/sentinel/sentinelonly.pm
# Display informative page to MSU users when SSO-based authentication
# is successful but there is no corresponding account in the 
# MSU LON-CAPA domain.
# 
# 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/
#
package Apache::sentinelonly;

use strict;
use lib qw(/home/httpd/lib/perl);
use Apache::Constants qw(:common);
use Apache::loncommon;
use Apache::lonnet;
use Apache::lonlocal;
use Apache::lonacc;
use Apache::coursecatalog;
use HTTP::Request::Common;
use LWP::UserAgent;

sub handler {
    my ($r) = @_;
    &Apache::loncommon::content_type($r,'text/html');
    $r->send_http_header;
    if ($r->header_only) {
        return OK;
    }

#    &Apache::lonacc::get_posted_cgi($r);
    &Apache::lonlocal::get_language_handle($r);

    my $username = $r->subprocess_env->get('REDIRECT_SSOUserUnknown');
    my $domain = $r->subprocess_env->get('REDIRECT_SSOUserDomain');
    my $domdesc = $Apache::lonnet::domaindescription{$domain};

    my %add_entries = (topmargin    => "0",
                       marginheight => "0",);
    my $start_page =
        &Apache::loncommon::start_page("MSU Single SignOn",'',
                                       {
                                        'add_entries' => \%add_entries,
                                        'no_inline_link'   => 1,});
    $r->print($start_page);
    $r->print(&mt("You successfully logged in via <b>Sentinel</b>, the MSUNet ID login service at <b>[_1]</b>, with a username of <b>[_2]</b>.",$domdesc,$username).'<br />'.&mt('However, LON-CAPA does <b>not</b> recognize your username as valid.').'<br /><br />'.&mt('If you are MSU <b>faculty</b> or <b>staff</b> this may be because you use a LON-CAPA account which is different from your MSUNet ID.').' '.&mt('If so, please login <a href="[_1]">here</a>.','/adm/login').'<br /><br />'.&mt('If you are an MSU <b>student</b> ...').'<br />');
    $r->rflush();

    my $usercourses = &query_LC_classlists($username);
    if ($usercourses != -1) {
        if ($usercourses eq '') {
            $r->print(&mt('You are <b>not</b> a registered student in any official [_1] courses from the last two years, which are using LON-CAPA.',$domdesc).'<br />'.&mt('As a result a LON-CAPA user account has <b>not</b> been created for you.'));
        } else {
            $usercourses =~tr/A-Z/a-z/;
            my $output = &check_courses($domain,$usercourses);
            if ($output) {
                $r->print(&mt('The following is a list of your section affiliation in all official courses which used LON-CAPA in the last two years in which you were a registered student.').'<br /><br />');
                $r->print($output);
            } else {
                $r->print(&mt('You are not currently in any sections of courses for which automatic enrollment in the corresponding LON-CAPA course is configured.').'<br />'.&mt('As a result a LON-CAPA user account has <b>not</b> yet been created for you.')); 
            }
        }
        $r->print('<br /><br />');
    }
    &Apache::lonnet::logthis("No LON-CAPA account for $username:$domain authenticated by SSO");
    my $catalogurl = '/adm/coursecatalog';
    my $ssologout = 'https://login.msu.edu/Logout.asp';
    $r->print(&mt('If you are registered in a course at MSU which will be using LON-CAPA, an account for your MSUNet ID may be lacking for one of the following reasons:').'
    <ul>
     <li>'.&mt('The course has yet to be created.').'</li>
     <li>'.&mt('Automatic enrollment of registered students has not been enabled for the course.').'</li>
     <li>'.&mt('You are in a section of course for which automatic enrollment in the corresponding LON-CAPA course is not active.').'</li>  
     <li>'.&mt('The start date for automated enrollment has yet to be reached.').'</li>
     <li>'.&mt('You registered for the course within the last 48 hours - there is a time lag between the time you register, and the time this information becomes available for the nightly update of LON-CAPA course rosters.').'</li>
     </ul>'.&mt("The <a href=\"[_1]\"/>Course Catalog</a> provides information about all MSU courses for which LON-CAPA courses have been created.",$catalogurl));
    $r->print('<br /><br />'.&mt("<a href=\"[_1]\">Logout from Single SignOn</a>?",$ssologout)); 
    $r->print(&Apache::loncommon::end_page());
    return OK;
}

sub query_LC_classlists {
    my ($user) = @_;
    my $URL = "http://s10.lite.msu.edu/cgi-bin/LC_classlist_check.pl?username=$user";
    my $request = new HTTP::Request;
    $request = GET $URL;
    my $res = LWP::UserAgent->new->request($request);
    if ($res->is_success) {
        my $dump = $res->content;
        return $dump;
    } else {
        &Apache::lonnet::logthis("An error occurred checking the classlist database: $res->error"); 
        return -1;
    }
}

sub check_courses {
    my ($dom,$usercourses) = @_;
    my ($output,%matches,%stucourse,@lines,%matchedsec);
    my ($instcodes,$allcourses);
    if ($usercourses =~ /\n/s) {
        @lines = split/\n/,$usercourses;
    } else {
        @lines = ($usercourses);
    }
    if (@lines > 0) {
        ($instcodes,$allcourses) = &get_official_courses($dom);
        foreach my $item (@lines) {
            my ($code,$seclist) = split(/=/,$item);
            my @sections = split(/:/,$seclist);
            if (defined($instcodes->{$code})) {
                my @sections = split(/:/,$seclist);
                if (ref($stucourse{$code}) eq 'ARRAY') {
                    foreach my $sec (@sections) {
                        if (!grep(/^\Q$sec\E$/,@{$stucourse{$code}{sections}})) {
                            push(@{$stucourse{$code}{sections}},$sec);
                        }
                    }
                } else {
                    @{$stucourse{$code}{sections}} = @sections;
                }
            }
        }
    }
    if (keys(%stucourse) > 0) {
        foreach my $code (keys(%stucourse)) {
            if (ref($instcodes) eq 'HASH') {  
                foreach my $cid (@{$instcodes->{$code}}) {
                    my %courseinfo =
                        &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
                    my ($instseclist,$numsec) = 
                        &Apache::coursecatalog::identify_sections($courseinfo{'internal.sectionnums'});
                    my @instsecs = split(/, /,$instseclist);
                    foreach my $stusec (@{$stucourse{$code}{sections}}) {
                        if (grep(/^\Q$stusec\E$/,@instsecs)) {  
                            $matches{$cid} = $allcourses->{$cid};
                            push(@{$matchedsec{$cid}},$stusec); 
                        }
                    } 
                }
            }
        }
    }
    if (keys(%matches) > 0) {
        $output = &Apache::coursecatalog::construct_data_table(1,\%matches,1,\%matchedsec);
    }
    return $output;
}

sub get_official_courses {
    my ($dom) = @_;
    my %allcourses = 
        &Apache::lonnet::courseiddump($dom,'.',1,'.','.','.',undef,undef,'Course');
    my %instcodes;
    foreach my $cid (keys(%allcourses)) {
        my ($description,$code,$other) = split(/:/,$allcourses{$cid},3);
        if ($code ne '') {
            push(@{$instcodes{$code}},$cid);
        }
    }
    return (\%instcodes,\%allcourses);
}

1;

Index: modules/msu/sentinel/sentinel.conf_frag
+++ modules/msu/sentinel/sentinel.conf_frag
<LocationMatch "^/adm/sso_failed_login">
SetHandler perl-script
PerlHandler Apache::sentinelonly
ErrorDocument     500 /adm/errorhandler
</LocationMatch>