[LON-CAPA-cvs] cvs: loncom(version_2_11_X) /interface loncreateuser.pm

raeburn raeburn at source.lon-capa.org
Sat Oct 22 13:57:55 EDT 2016


raeburn		Sat Oct 22 17:57:55 2016 EDT

  Modified files:              (Branch: version_2_11_X)
    /loncom/interface	loncreateuser.pm 
  Log:
  - For 2.11
    - Backport 1.414, 1.415, 1.416, 1.417
  
  
-------------- next part --------------
Index: loncom/interface/loncreateuser.pm
diff -u loncom/interface/loncreateuser.pm:1.406.2.4 loncom/interface/loncreateuser.pm:1.406.2.5
--- loncom/interface/loncreateuser.pm:1.406.2.4	Sat Oct 22 15:53:55 2016
+++ loncom/interface/loncreateuser.pm	Sat Oct 22 17:57:54 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Create a user
 #
-# $Id: loncreateuser.pm,v 1.406.2.4 2016/10/22 15:53:55 raeburn Exp $
+# $Id: loncreateuser.pm,v 1.406.2.5 2016/10/22 17:57:54 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -527,6 +527,72 @@
            &Apache::loncommon::end_data_table();
 }
 
+sub domadhocroles {
+    my ($ccuname,$ccdomain) = @_;
+    my $confname = &Apache::lonnet::get_domainconfiguser($env{'request.role.domain'});
+    my %existing=&Apache::lonnet::dump('roles',$env{'request.role.domain'},
+                                       $confname,'rolesdef_');
+    my $output;
+    if (keys(%existing) > 0) {
+        my @current;
+        my $curradhoc = 'adhocroles.'.$env{'request.role.domain'};
+        my %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname,$curradhoc);
+        if ($userenv{$curradhoc}) {
+            @current = split(/,/,$userenv{$curradhoc});
+        }
+        my %customroles;
+        foreach my $key (keys(%existing)) {
+            if ($key=~/^rolesdef\_(\w+)$/) {
+                my $rolename = $1;
+                my %privs;
+                ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});
+                $customroles{$rolename} = \%privs;
+            }
+        }
+        $output = '<br /><h3>'.
+                  &mt('Ad Hoc Course Roles Selectable via Helpdesk Role').
+                  '</h3>'."\n".
+                  &Apache::loncommon::start_data_table().
+                  &Apache::loncommon::start_data_table_header_row().
+                  '<th>'.&mt('Action').'</th><th>'.&mt('Role').'</th>'.
+                  '<th>'.&mt('Privileges in Course').'<th>'.
+                  &Apache::loncommon::end_data_table_header_row();
+        foreach my $key (sort(keys(%customroles))) {
+            $output .= &Apache::loncommon::start_data_table_row();
+            if (grep(/^\Q$key\E$/, at current)) {
+                $output .= '<td><label>'.
+                           '<input type="checkbox" name="adhocroledel" value="'.$key.'" />'.
+                           &mt('Delete').'</label>'.
+                           '</td>';
+            } else {
+                $output .= '<td><label>'.
+                           '<input type="checkbox" name="adhocroleadd" value="'.$key.'" />'.
+                           &mt('Add').'</label>'.
+                           '</td>';
+            }
+            $output .= '<td>'.$key.'</td><td>';
+            foreach my $level ('course','domain','system') {
+                if ($customroles{$key}{$level}) {
+                    my $suffix;
+                    if (($level eq 'domain') || ($level eq 'system')) {
+                        $suffix = ' ('.&mt($level).')';
+                    }
+                    my @privs = split(/:/,$customroles{$key}{$level});
+                    foreach my $item (@privs) {
+                        next if ($item eq '');
+                        my ($priv,$cond) = split(/\&/,$item);
+                        $output .= &Apache::lonnet::plaintext($priv,'Course').$suffix.'<br />';
+                    }
+                }
+            }
+            $output .= '</td>'.
+                       &Apache::loncommon::end_data_table_row();
+        }
+        $output .= &Apache::loncommon::end_data_table();
+    }
+    return $output;
+}
+
 sub courserequest_titles {
     my %titles = &Apache::lonlocal::texthash (
                                    official   => 'Official',
@@ -666,6 +732,8 @@
         $helpitem = 'Course_Editing_Custom_Roles';
     } elsif ($env{'form.action'} eq 'singlestudent') {
         $helpitem = 'Course_Add_Student';
+    } elsif ($env{'form.action'} eq 'accesslogs') {
+        $helpitem = 'Domain_User_Access_Logs';
     }
     my %breadcrumb_text = &singleuser_breadcrumb($crstype);
     if ($env{'form.action'} eq 'custom') {
@@ -695,6 +763,7 @@
                     'srst' => 'Search for a user and enroll as a student',
                     'srme' => 'Search for a user and enroll as a member',
                     'srad' => 'Search for a user and modify/add user information or roles',
+                    'srva' => 'Search for a user and view access log information',
 		    'usr'  => "Username",
                     'dom'  => "Domain",
                     'ecrp' => "Define or Edit Custom Role",
@@ -747,12 +816,17 @@
             } else {
                 $actiontext = $lt{'srst'};
             }
+        } elsif ($env{'form.action'} eq 'accesslogs') {
+            $actiontext = $lt{'srva'};
         }
         $r->print("<h3>$actiontext</h3>");
         if ($env{'form.origform'} ne 'crtusername') {
-            $r->print("\n".$response);
+            if ($response) {
+               $r->print("\n<div>$response</div>".
+                         '<br clear="all" />');
+            }
         }
-        $r->print(&entry_form($defdom,$srch,$forcenewuser,$context,$response,$crstype));
+        $r->print(&entry_form($defdom,$srch,$forcenewuser,$context,$response,$crstype,1));
     }
 }
 
@@ -795,7 +869,7 @@
 }
 
 sub entry_form {
-    my ($dom,$srch,$forcenewuser,$context,$responsemsg,$crstype) = @_;
+    my ($dom,$srch,$forcenewuser,$context,$responsemsg,$crstype,$fixeddom) = @_;
     my ($usertype,$inexact);
     if (ref($srch) eq 'HASH') {
         if (($srch->{'srchin'} eq 'dom') &&
@@ -815,10 +889,12 @@
         &Apache::lonuserutils::can_create_user($dom,$context,$usertype);
     my ($userpicker,$cansearch) = 
        &Apache::loncommon::user_picker($dom,$srch,$forcenewuser,
-                                       'document.crtuser',$cancreate,$usertype);
+                                       'document.crtuser',$cancreate,$usertype,$context,$fixeddom);
     my $srchbutton = &mt('Search');
     if ($env{'form.action'} eq 'singlestudent') {
         $srchbutton = &mt('Search and Enroll');
+    } elsif ($env{'form.action'} eq 'accesslogs') {
+        $srchbutton = &mt('Search');
     } elsif ($cancreate && $responsemsg ne '' && $inexact) {
         $srchbutton = &mt('Search or Add New User');
     }
@@ -835,7 +911,7 @@
     } else {
         $output = '<p>'.$userpicker.'</p>';
     }
-    if ($env{'form.phase'} eq '') {
+    if (($env{'form.phase'} eq '') && ($env{'form.action'} ne 'accesslogs')) {
         my $defdom=$env{'request.role.domain'};
         my $domform = &Apache::loncommon::select_dom_form($defdom,'srchdomain');
         my %lt=&Apache::lonlocal::texthash(
@@ -951,9 +1027,11 @@
                                        'usrch'          => "User Search to add/modify roles",
                                        'stusrch'        => "User Search to enroll student",
                                        'memsrch'        => "User Search to enroll member",
+                                       'srcva'          => "Search for a user and view access log information",
                                        'usel'           => "Select a user to add/modify roles",
                                        'stusel'         => "Select a user to enroll as a student",
                                        'memsel'         => "Select a user to enroll as a member",
+                                       'vacsel'         => "Select a user to view access log",
                                        'username'       => "username",
                                        'domain'         => "domain",
                                        'lastname'       => "last name",
@@ -1002,6 +1080,10 @@
                 $r->print($lt{'stusel'});
             }
             $r->print('</h3>');
+        } elsif ($env{'form.action'} eq 'accesslogs') {
+            $r->print("<b>$lt{'srcva'}</b><br />");
+            $r->print(&entry_form($srch->{'srchdomain'},$srch,undef,'accesslogs',undef,undef,1));
+            $r->print('<h3>'.$lt{'vacsel'}.'</h3>');
         }
     }
     $r->print('<form name="usersrchform" method="post" action="">'.
@@ -1236,7 +1318,7 @@
     }
     my $title = '';
     if ($newuser) {
-        my ($portfolioform,$domroleform);
+        my ($portfolioform,$domroleform,$adhocroleform);
         if ((&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) ||
             (&Apache::lonnet::allowed('mut',$env{'request.role.domain'}))) {
             # Current user has quota or user tools modification privileges
@@ -1246,6 +1328,12 @@
             ($ccdomain eq $env{'request.role.domain'})) {
             $domroleform = '<br />'.&domainrole_req($ccuname,$ccdomain);
         }
+        if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+            $adhocroleform = &domadhocroles($ccuname,$ccdomain);
+            if ($adhocroleform) {
+                $adhocroleform = '<br />'.$adhocroleform;
+            }
+        }
         &initialize_authen_forms($ccdomain,$formname);
         my %lt=&Apache::lonlocal::texthash(
                 'lg'             => 'Login Data',
@@ -1356,7 +1444,7 @@
         } else {
             $r->print(&Apache::lonuserutils::set_login($ccdomain,$authformkrb,$authformint,$authformloc)); 
         }
-        $r->print($portfolioform.$domroleform);
+        $r->print($portfolioform.$domroleform.$adhocroleform);
         if ($env{'form.action'} eq 'singlestudent') {
             $r->print(&date_sections_select($context,$newuser,$formname,
                                             $permission,$crstype,$ccuname,
@@ -1393,7 +1481,7 @@
             $r->print(&Apache::loncommon::end_data_table());
         }
         $r->print('</div>');
-        my @order = ('auth','quota','tools','requestauthor');
+        my @order = ('auth','quota','tools','requestauthor','adhocroles');
         my %user_text;
         my ($isadv,$isauthor) = 
             &Apache::lonnet::is_advanced_user($ccuname,$ccdomain);
@@ -1402,6 +1490,9 @@
             && ($env{'request.role.domain'} eq $ccdomain)) {
             $user_text{'requestauthor'} = &domainrole_req($ccuname,$ccdomain);
         }
+        if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+            $user_text{'adhocroles'} = &domadhocroles($ccuname,$ccdomain);
+        }
         $user_text{'auth'} =  &user_authentication($ccuname,$ccdomain,$formname);
         if ((&Apache::lonnet::allowed('mpq',$ccdomain)) ||
             (&Apache::lonnet::allowed('mut',$ccdomain))) {
@@ -1528,6 +1619,10 @@
         }
         $breadcrumb_text{'userpicked'} = 'Select a user',
         $breadcrumb_text{'modify'} = 'Set section/dates',
+    } elsif ($env{'form.action'} eq 'accesslogs') {
+        $breadcrumb_text{'search'} = 'View access logs for a user';
+        $breadcrumb_text{'userpicked'} = 'Select a user',
+        $breadcrumb_text{'activity'} = 'Activity',
     } else {
         $breadcrumb_text{'search'} = 'Create/modify a user';
         $breadcrumb_text{'userpicked'} = 'Select a user',
@@ -2694,6 +2789,12 @@
                                                     $newcustom{'requestauthor'},
                                                     \%changeHash,'requestauthor');
                 }
+                if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+                    my @adds = &Apache::loncommon::get_env_multiple('form.adhocroleadd');
+                    if (&adhocrole_changes(\%changeHash)) {
+                        $changed{'adhocroles.'.$env{'request.role.domain'}} = $changeHash{'adhocroles.'.$env{'request.role.domain'}};
+                    }
+                }
             }
             if ($canmodify_status{'inststatus'}) {
                 if (exists($env{'form.inststatus'})) {
@@ -2757,7 +2858,7 @@
              'requestcourses.community','requestcourses.textbook',
              'reqcrsotherdom.official','reqcrsotherdom.unofficial',
              'reqcrsotherdom.community','reqcrsotherdom.textbook',
-             'requestauthor'],
+             'requestauthor','adhocroles.'.$env{'request.role.domain'}],
               $env{'form.ccdomain'},$env{'form.ccuname'});
         my ($tmp) = keys(%userenv);
         if ($tmp =~ /^(con_lost|error)/i) { 
@@ -2896,6 +2997,7 @@
                 &Apache::loncommon::default_quota($env{'form.ccdomain'},$oldinststatus,$name);
             ($newdefquota{$name},$newsettingstatus{$name}) = ($olddefquota{$name},$oldsettingstatus{$name});
         }
+        push(@disporder,'adhocroles');
         my %canshow;
         if (&Apache::lonnet::allowed('mpq',$env{'form.ccdomain'})) {
             $canshow{'quota'} = 1;
@@ -2914,6 +3016,9 @@
         if (&Apache::lonnet::allowed('cau',$env{'form.ccdomain'})) {
             $canshow{'requestauthor'} = 1;
         }
+        if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+            $canshow{'adhocroles'} = 1;
+        }
         my (%changeHash,%changed);
         if ($oldinststatus eq '') {
             $oldsettings{'inststatus'} = $othertitle; 
@@ -3027,6 +3132,14 @@
                 &tool_changes('reqcrsotherdom',\@requestcourses,\%oldsettings,\%oldsettingstext,
                               \%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext);
             }
+            if ($userenv{'adhocroles.'.$env{'request.role.domain'}}) {
+                $changeHash{'adhocroles.'.$env{'request.role.domain'}} = $userenv{'adhocroles.'.$env{'request.role.domain'}};
+            }
+            if (&adhocrole_changes(\%changeHash,\%userenv)) {
+                $changed{'adhocroles'} = 1;
+                $oldsettings{'adhocroles'} = $userenv{'adhocroles.'.$env{'request.role.domain'}};
+                $newsettings{'adhocroles'} = $changeHash{'adhocroles.'.$env{'request.role.domain'}};
+            }
         }
         foreach my $item (@userinfo) {
             if ($env{'form.c'.$item} ne $userenv{$item}) {
@@ -3068,6 +3181,9 @@
           &Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'},
                                             $key,'reload','requestauthor');
                                 }
+                            } elsif ($key eq 'adhocroles') {
+                                $newenvhash{'adhocroles.'.$env{'request.role.domain'}} =
+                                    $changeHash{'adhocroles.'.$env{'request.role.domain'}};
                             } elsif ($key ne 'quota') {
                                 $newenvhash{'environment.tools.'.$key} = 
                                     $changeHash{'tools.'.$key};
@@ -3115,7 +3231,7 @@
                                   \%newsettingstext);
                 if ($env{'form.cid'} ne $userenv{'id'}) {
                     &Apache::lonnet::idput($env{'form.ccdomain'},
-                         ($env{'form.ccuname'} => $env{'form.cid'}));
+                         {$env{'form.ccuname'} => $env{'form.cid'}});
                     if (($recurseid) &&
                         (&Apache::lonnet::allowed('mau',$env{'form.ccdomain'}))) {
                         my $idresult = 
@@ -3259,6 +3375,7 @@
          'community'      => 'Can Request Communities',
          'textbook'       => 'Can Request Textbook Courses',
          'requestauthor'  => 'Can Request Author Role',
+         'adhocroles'     => 'Ad Hoc Roles Selectable via Helpdesk Role',
          'inststatus'     => "Affiliation",
          'prvs'           => 'Previous Value:',
          'chto'           => 'Changed To:'
@@ -3624,6 +3741,70 @@
     return;
 }
 
+sub adhocrole_changes {
+    my ($changehashref,$userenv) = @_;
+    my @adds = &Apache::loncommon::get_env_multiple('form.adhocroleadd');
+    my @dels = &Apache::loncommon::get_env_multiple('form.adhocroledel');
+    my (@saved, at added, at alladhoc,$changed);
+    my $adhoc_key = 'adhocroles.'.$env{'request.role.domain'};
+    if (!$env{'form.makeuser'}) {
+        if (ref($userenv) eq 'HASH') {
+            my @current;
+            if ($userenv->{$adhoc_key}) {
+                @current = split(/,/,$userenv->{$adhoc_key});
+                if (@dels) {
+                    foreach my $curr (@current) {
+                        next if ($curr eq '');
+                        unless (grep(/\Q$curr\E$/, at dels)) {
+                            push(@saved,$curr);
+                        }
+                    }
+                    $changed = 1;
+                } else {
+                    @saved = @current;
+                }
+            }
+        }
+    }
+    if (@adds) {
+        my $confname = &Apache::lonnet::get_domainconfiguser($env{'request.role.domain'});
+        my %existing=&Apache::lonnet::dump('roles',$env{'request.role.domain'},
+                                           $confname,'rolesdef_');
+        foreach my $poss (@adds) {
+            if (exists($existing{'rolesdef_'.$poss})) {
+                push(@added,$poss);
+                $changed = 1;
+            }
+        }
+    }
+    if (@added) {
+        if (@saved) {
+            foreach my $add (@added) {
+                unless (grep(/^\Q$add\E$/, at saved)) {
+                    push(@alladhoc,$add);
+                }
+            }
+        } else {
+            push(@alladhoc, at added);
+        }
+    }
+    if (@saved) {
+        push(@alladhoc, at saved);
+    }
+    if (@alladhoc) {
+        my $adhocstr = join(',',sort(@alladhoc));
+        $changehashref->{$adhoc_key} = $adhocstr;
+    } elsif (@dels) {
+        &Apache::lonnet::del('environment',[$adhoc_key],$env{'form.ccdomain'},$env{'form.ccuname'});
+        delete($changehashref->{$adhoc_key});
+        if (($env{'form.ccdomain'} eq $env{'user.domain'}) &&
+            ($env{'form.ccuname'} eq $env{'user.name'})) {
+            &Apache::lonnet::delenv($adhoc_key);
+        }
+    }
+    return $changed;
+}
+
 sub update_roles {
     my ($r,$context,$showcredits) = @_;
     my $now=time;
@@ -4154,7 +4335,7 @@
 # ========================================================== Custom Role Editor
 
 sub custom_role_editor {
-    my ($r,$brcrum) = @_;
+    my ($r,$brcrum,$prefix) = @_;
     my $action = $env{'form.customroleaction'};
     my $rolename; 
     if ($action eq 'new') {
@@ -4169,7 +4350,7 @@
         $context = 'course';
     } else {
         $context = 'domain';
-        $crstype = $env{'form.templatecrstype'};
+        $crstype = 'course';
     }
 
     $rolename=~s/[^A-Za-z0-9]//gs;
@@ -4178,120 +4359,54 @@
         return;
     }
 
-# ------------------------------------------------------- What can be assigned?
-    my %full=();
-    my %courselevel=();
-    my %courselevelcurrent=();
-    my $syspriv='';
-    my $dompriv='';
-    my $coursepriv='';
-    my $body_top;
-    my $newrole;
+    my $formname = 'form1';
+    my %privs=();
+    my $body_top = '<h2>';
+# ------------------------------------------------------- Does this role exist?
     my ($rdummy,$roledef)=
 			 &Apache::lonnet::get('roles',["rolesdef_$rolename"]);
-# ------------------------------------------------------- Does this role exist?
-    $body_top .= '<h2>';
     if (($rdummy ne 'con_lost') && ($roledef ne '')) {
-	$body_top .= &mt('Existing Role').' "';
+        $body_top .= &mt('Existing Role').' "';
 # ------------------------------------------------- Get current role privileges
-	($syspriv,$dompriv,$coursepriv)=split(/\_/,$roledef);
-        if ($crstype eq 'Community') {
-            $syspriv =~ s/bre\&S//;   
+        ($privs{'system'},$privs{'domain'},$privs{'course'})=split(/\_/,$roledef);
+        if ($privs{'system'} =~ /bre\&S/) {
+            if ($context eq 'domain') {
+                $crstype = 'Course';
+            } elsif ($crstype eq 'Community') {
+                $privs{'system'} =~ s/bre\&S//;
+            }
+        } elsif ($context eq 'domain') {
+            $crstype = 'Course';
         }
     } else {
-        $newrole = 1;
-	$body_top .= &mt('New Role').' "';
-	$roledef='';
+        $body_top .= &mt('New Role').' "';
+        $roledef='';
     }
     $body_top .= $rolename.'"</h2>';
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict='F'; }
-        $courselevel{$priv}=$restrict;
-        if ($coursepriv=~/\:$priv/) {
-	    $courselevelcurrent{$priv}=1;
-	}
-	$full{$priv}=1;
-    }
-    my %domainlevel=();
-    my %domainlevelcurrent=();
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict='F'; }
-        $domainlevel{$priv}=$restrict;
-        if ($dompriv=~/\:$priv/) {
-	    $domainlevelcurrent{$priv}=1;
-	}
-	$full{$priv}=1;
-    }
-    my %systemlevel=();
-    my %systemlevelcurrent=();
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict='F'; }
-        $systemlevel{$priv}=$restrict;
-        if ($syspriv=~/\:$priv/) {
-	    $systemlevelcurrent{$priv}=1;
-	}
-	$full{$priv}=1;
-    }
+
+# ------------------------------------------------------- What can be assigned?
+    my %full=();
+    my %levels=(
+                 course => {},
+                 domain => {},
+                 system => {},
+               );
+    my %levelscurrent=(
+                        course => {},
+                        domain => {},
+                        system => {},
+                      );
+    &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
     my ($jsback,$elements) = &crumb_utilities();
-    my $button_code = "\n";
-    my $head_script = "\n";
-    $head_script .= '<script type="text/javascript">'."\n"
-                   .'// <![CDATA['."\n";
-    my @template_roles = ("in","ta","ep");
-    if ($context eq 'domain') {
-        push(@template_roles,"ad");
-    }
-    push(@template_roles,"st");
-    if ($crstype eq 'Community') {
-        unshift(@template_roles,'co');
-    } else {
-        unshift(@template_roles,'cc');
-    }
-    foreach my $role (@template_roles) {
-        $head_script .= &make_script_template($role,$crstype);
-        $button_code .= &make_button_code($role,$crstype).' ';
-    }
-    my $context_code;
-    if ($context eq 'domain') {
-        my $checkedCommunity = '';
-        my $checkedCourse = ' checked="checked"';
-        if ($env{'form.templatecrstype'} eq 'Community') {
-            $checkedCommunity = $checkedCourse;
-            $checkedCourse = '';
-        }
-        $context_code = '<label>'.
-                        '<input type="radio" name="templatecrstype" value="Course"'.$checkedCourse.' onclick="this.form.submit();">'.
-                        &mt('Course').
-                        '</label>'.(' ' x2).
-                        '<label>'.
-                        '<input type="radio" name="templatecrstype" value="Community"'.$checkedCommunity.' onclick="this.form.submit();">'.
-                        &mt('Community').
-                        '</label>'.
-                        '</fieldset>'.
-                        '<input type="hidden" name="customroleaction" value="'.
-                        $action.'" />';
-        if ($env{'form.customroleaction'} eq 'new') {
-            $context_code .= '<input type="hidden" name="newrolename" value="'.
-                             $rolename.'" />';
-        } else {
-            $context_code .= '<input type="hidden" name="rolename" value="'.
-                             $rolename.'" />';
-        }
-        $context_code .= '<input type="hidden" name="action" value="custom" />'.
-                         '<input type="hidden" name="phase" value="selected_custom_edit" />';
-    }
-
-    $head_script .= "\n".$jsback."\n"
-                   .'// ]]>'."\n"
-                   .'</script>'."\n";
+    my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
+    my $head_script =
+        &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,
+                                                  \%full,\@templateroles,$jsback);
     push (@{$brcrum},
-              {href => "javascript:backPage(document.form1,'pickrole','')",
+              {href => "javascript:backPage(document.$formname,'pickrole','')",
                text => "Pick custom role",
                faq  => 282,bug=>'Instructor Interface',},
-              {href => "javascript:backPage(document.form1,'','')",
+              {href => "javascript:backPage(document.$formname,'','')",
                text => "Edit custom role",
                faq  => 282,
                bug  => 'Instructor Interface',
@@ -4299,149 +4414,35 @@
               );
     my $args = { bread_crumbs          => $brcrum,
                  bread_crumbs_component => 'User Management'};
- 
+
     $r->print(&Apache::loncommon::start_page('Custom Role Editor',
                                              $head_script,$args).
               $body_top);
-    my %lt=&Apache::lonlocal::texthash(
-		    'prv'  => "Privilege",
-		    'crl'  => "Course Level",
-                    'dml'  => "Domain Level",
-                    'ssl'  => "System Level");
-
-    $r->print('<div class="LC_left_float">'
-             .'<form action=""><fieldset>'
-             .'<legend>'.&mt('Select a Template').'</legend>'
-             .$button_code
-             .'</fieldset></form></div>');
-    if ($context_code) {
-        $r->print('<div class="LC_left_float">'
-                 .'<form action="/adm/createuser" method="post"><fieldset>'
-                 .'<legend>'.&mt('Context').'</legend>'
-                 .$context_code
-                 .'</form>'
-                 .'</div>'
-        );
-    }
-    $r->print('<br clear="all" />');
+    $r->print('<form name="'.$formname.'" method="post" action="">'."\n".
+              &Apache::lonuserutils::custom_role_header($context,$crstype,
+                                                        \@templateroles,$prefix));
 
     $r->print(<<ENDCCF);
-<form name="form1" method="post" action="">
 <input type="hidden" name="phase" value="set_custom_roles" />
 <input type="hidden" name="rolename" value="$rolename" />
 ENDCCF
-    $r->print(&Apache::loncommon::start_data_table().
-              &Apache::loncommon::start_data_table_header_row(). 
-'<th>'.$lt{'prv'}.'</th><th>'.$lt{'crl'}.'</th><th>'.$lt{'dml'}.
-'</th><th>'.$lt{'ssl'}.'</th>'.
-              &Apache::loncommon::end_data_table_header_row());
-    foreach my $priv (sort(keys(%full))) {
-        my $privtext = &Apache::lonnet::plaintext($priv,$crstype);
-        $r->print(&Apache::loncommon::start_data_table_row().
-	          '<td>'.$privtext.'</td><td>'.
-    ($courselevel{$priv}?'<input type="checkbox" name="'.$priv.'_c"'.
-    ($courselevelcurrent{$priv}?' checked="checked"':'').' />':' ').
-    '</td><td>'.
-    ($domainlevel{$priv}?'<input type="checkbox" name="'.$priv.'_d"'.
-    ($domainlevelcurrent{$priv}?' checked="checked"':'').' />':' ').
-    '</td><td>');
-        if ($priv eq 'bre' && $crstype eq 'Community') {
-            $r->print(' ');  
-        } else {
-            $r->print($systemlevel{$priv}?'<input type="checkbox" name="'.$priv.'_s"'.
-                      ($systemlevelcurrent{$priv}?' checked="checked"':'').' />':' ');
-        }
-        $r->print('</td>'.
-                  &Apache::loncommon::end_data_table_row());
-    }
+    $r->print(&Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels,
+                                                       \%levelscurrent,$prefix));
     $r->print(&Apache::loncommon::end_data_table().
    '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'.
    '<input type="hidden" name="startrolename" value="'.$env{'form.rolename'}.
-   '" />'."\n".'<input type="hidden" name="currstate" value="" />'."\n".   
+   '" />'."\n".'<input type="hidden" name="currstate" value="" />'."\n".
    '<input type="reset" value="'.&mt("Reset").'" />'."\n".
    '<input type="submit" value="'.&mt('Save').'" /></form>');
 }
-# --------------------------------------------------------
-sub make_script_template {
-    my ($role,$crstype) = @_;
-    my %full_c=();
-    my %full_d=();
-    my %full_s=();
-    my $return_script;
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) {
-        my ($priv,$restrict)=split(/\&/,$item);
-        $full_c{$priv}=1;
-    }
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) {
-        my ($priv,$restrict)=split(/\&/,$item);
-        $full_d{$priv}=1;
-    }
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) {
-        next if (($crstype eq 'Community') && ($item eq 'bre&S'));
-        my ($priv,$restrict)=split(/\&/,$item);
-        $full_s{$priv}=1;
-    }
-    $return_script .= 'function set_'.$role.'() {'."\n";
-    my @temp = split(/:/,$Apache::lonnet::pr{$role.':c'});
-    my %role_c;
-    foreach my $priv (@temp) {
-        my ($priv_item, $dummy) = split(/\&/,$priv);
-        $role_c{$priv_item} = 1;
-    }
-    my %role_d;
-    @temp = split(/:/,$Apache::lonnet::pr{$role.':d'});
-    foreach my $priv(@temp) {
-        my ($priv_item, $dummy) = split(/\&/,$priv);
-        $role_d{$priv_item} = 1;
-    }
-    my %role_s;
-    @temp = split(/:/,$Apache::lonnet::pr{$role.':s'});
-    foreach my $priv(@temp) {
-        my ($priv_item, $dummy) = split(/\&/,$priv);
-        $role_s{$priv_item} = 1;
-    }
-    foreach my $priv_item (keys(%full_c)) {
-        my ($priv, $dummy) = split(/\&/,$priv_item);
-        if ((exists($role_c{$priv})) || (exists($role_d{$priv})) || 
-            (exists($role_s{$priv}))) {
-            $return_script .= "document.form1.$priv"."_c.checked = true;\n";
-        } else {
-            $return_script .= "document.form1.$priv"."_c.checked = false;\n";
-        }
-    }
-    foreach my $priv_item (keys(%full_d)) {
-        my ($priv, $dummy) = split(/\&/,$priv_item);
-        if ((exists($role_d{$priv})) || (exists($role_s{$priv}))) {
-            $return_script .= "document.form1.$priv"."_d.checked = true;\n";
-        } else {
-            $return_script .= "document.form1.$priv"."_d.checked = false;\n";
-        }
-    }
-    foreach my $priv_item (keys(%full_s)) {
-        my ($priv, $dummy) = split(/\&/,$priv_item);
-        if (exists($role_s{$priv})) {
-            $return_script .= "document.form1.$priv"."_s.checked = true;\n";
-        } else {
-            $return_script .= "document.form1.$priv"."_s.checked = false;\n";
-        }
-    }
-    $return_script .= '}'."\n";
-    return ($return_script);
-}
-# ----------------------------------------------------------
-sub make_button_code {
-    my ($role,$crstype) = @_;
-    my $label = &Apache::lonnet::plaintext($role,$crstype);
-    my $button_code = '<input type="button" onclick="set_'.$role.'()" value="'.$label.'" />';
-    return ($button_code);
-}
+
 # ---------------------------------------------------------- Call to definerole
 sub set_custom_role {
-    my ($r,$context,$brcrum) = @_;
+    my ($r,$context,$brcrum,$prefix) = @_;
     my $rolename=$env{'form.rolename'};
     $rolename=~s/[^A-Za-z0-9]//gs;
     if (!$rolename) {
-	&custom_role_editor($r,$brcrum);
+	&custom_role_editor($r,$brcrum,$prefix);
         return;
     }
     my ($jsback,$elements) = &crumb_utilities();
@@ -4466,7 +4467,7 @@
          help => 'Course_Editing_Custom_Roles'},
         );
     my $args = { bread_crumbs           => $brcrum,
-                 bread_crumbs_component => 'User Management'}; 
+                 bread_crumbs_component => 'User Management'};
     $r->print(&Apache::loncommon::start_page('Save Custom Role',$jscript,$args));
 
     my $newrole;
@@ -4483,38 +4484,13 @@
         $newrole = 1;
     }
     $r->print($rolename.'"</h3>');
-# ------------------------------------------------------- What can be assigned?
-    my $sysrole='';
-    my $domrole='';
-    my $courole='';
-
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict=''; }
-        if ($env{'form.'.$priv.'_c'}) {
-	    $courole.=':'.$item;
-	}
-    }
+# ------------------------------------------------- Assign role and show result
 
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict=''; }
-        if ($env{'form.'.$priv.'_d'}) {
-	    $domrole.=':'.$item;
-	}
-    }
-
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict=''; }
-        if ($env{'form.'.$priv.'_s'}) {
-	    $sysrole.=':'.$item;
-	}
-    }
-    # Assign role; Compile and show result
     my $errmsg;
-    my $result =
-        &Apache::lonnet::definerole($rolename,$sysrole,$domrole,$courole);
+    my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$prefix);
+    # Assign role and return result
+    my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
+                                             $newprivs{'c'});
     if ($result ne 'ok') {
         $errmsg = ': '.$result;
     }
@@ -4642,8 +4618,9 @@
         } else {
             &Apache::lonuserutils::print_first_users_upload_form($r,$context);
         }
-    } elsif ((($env{'form.action'} eq 'singleuser') || ($env{'form.action'}
-             eq 'singlestudent')) && ($permission->{'cusr'})) {
+    } elsif (((($env{'form.action'} eq 'singleuser') || ($env{'form.action'}
+              eq 'singlestudent')) && ($permission->{'cusr'})) ||
+             (($env{'form.action'} eq 'accesslogs') && ($permission->{'activity'}))) {
         my $phase = $env{'form.phase'};
         my @search = ('srchterm','srchby','srchin','srchtype','srchdomain');
 	&Apache::loncreateuser::restore_prev_selections();
@@ -4652,7 +4629,7 @@
 	    $srch->{$item} = $env{'form.'.$item};
 	}
         if (($phase eq 'get_user_info') || ($phase eq 'userpicked') ||
-            ($phase eq 'createnewuser')) {
+            ($phase eq 'createnewuser') || ($phase eq 'activity')) {
             if ($env{'form.phase'} eq 'createnewuser') {
                 my $response;
                 if ($env{'form.srchterm'} !~ /^$match_username$/) {
@@ -4682,8 +4659,8 @@
                     &print_user_selection_page($r,$response,$srch,$results,
                                                \@search,$context,undef,$crstype,
                                                $brcrum);
-                } elsif ($currstate eq 'modify') {
-                    my ($ccuname,$ccdomain);
+                } elsif (($currstate eq 'modify') || ($env{'form.action'} eq 'accesslogs')) {
+                    my ($ccuname,$ccdomain,$uhome);
                     if (($srch->{'srchby'} eq 'uname') && 
                         ($srch->{'srchtype'} eq 'exact')) {
                         $ccuname = $srch->{'srchterm'};
@@ -4694,12 +4671,32 @@
                     }
                     $ccuname =&LONCAPA::clean_username($ccuname);
                     $ccdomain=&LONCAPA::clean_domain($ccdomain);
-                    if ($env{'form.forcenewuser'}) {
-                        $response = '';
+                    if ($env{'form.action'} eq 'accesslogs') {
+                        my $uhome;
+                        if (($ccuname ne '') && ($ccdomain ne '')) {
+                           $uhome = &Apache::lonnet::homeserver($ccuname,$ccdomain);
+                        }
+                        if (($uhome eq '') || ($uhome eq 'no_host')) {
+                            $env{'form.phase'} = '';
+                            undef($forcenewuser);
+                            #if ($response) {
+                            #    unless ($response =~ m{\Q<br /><br />\E$}) {
+                            #        $response .= '<br /><br />';
+                            #    }
+                            #}
+                            &print_username_entry_form($r,$context,$response,$srch,
+                                                       $forcenewuser,$crstype,$brcrum);
+                        } else {
+                            &print_useraccesslogs_display($r,$ccuname,$ccdomain,$permission,$brcrum);
+                        }
+                    } else {
+                        if ($env{'form.forcenewuser'}) {
+                            $response = '';
+                        }
+                        &print_user_modification_page($r,$ccuname,$ccdomain,
+                                                      $srch,$response,$context,
+                                                      $permission,$crstype,$brcrum);
                     }
-                    &print_user_modification_page($r,$ccuname,$ccdomain,
-                                                  $srch,$response,$context,
-                                                  $permission,$crstype,$brcrum);
                 } elsif ($currstate eq 'query') {
                     &print_user_query_page($r,'createuser',$brcrum);
                 } else {
@@ -4710,9 +4707,17 @@
             } elsif ($env{'form.phase'} eq 'userpicked') {
                 my $ccuname = &LONCAPA::clean_username($env{'form.seluname'});
                 my $ccdomain = &LONCAPA::clean_domain($env{'form.seludom'});
-                &print_user_modification_page($r,$ccuname,$ccdomain,$srch,'',
-                                              $context,$permission,$crstype,
-                                              $brcrum);
+                if ($env{'form.action'} eq 'accesslogs') {
+                    &print_useraccesslogs_display($r,$ccuname,$ccdomain,$permission,$brcrum);
+                } else {
+                    &print_user_modification_page($r,$ccuname,$ccdomain,$srch,'',
+                                                  $context,$permission,$crstype,
+                                                  $brcrum);
+                }
+            } elsif ($env{'form.action'} eq 'accesslogs') {
+                my $ccuname = &LONCAPA::clean_username($env{'form.accessuname'});
+                my $ccdomain = &LONCAPA::clean_domain($env{'form.accessudom'});
+                &print_useraccesslogs_display($r,$ccuname,$ccdomain,$permission,$brcrum);
             }
         } elsif ($env{'form.phase'} eq 'update_user_data') {
             &update_user_data($r,$context,$crstype,$brcrum,$showcredits);
@@ -4721,10 +4726,11 @@
                                        $brcrum);
         }
     } elsif ($env{'form.action'} eq 'custom' && $permission->{'custom'}) {
+        my $prefix;
         if ($env{'form.phase'} eq 'set_custom_roles') {
-            &set_custom_role($r,$context,$brcrum);
+            &set_custom_role($r,$context,$brcrum,$prefix);
         } else {
-            &custom_role_editor($r,$brcrum);
+            &custom_role_editor($r,$brcrum,$prefix);
         }
     } elsif (($env{'form.action'} eq 'processauthorreq') &&
              ($permission->{'cusr'}) && 
@@ -5050,19 +5056,7 @@
                           $cdom,$cnum,$coursedesc));
         }
     } elsif ($env{'form.action'} eq 'changelogs') {
-        my $helpitem;
-        if ($context eq 'course') {
-            $helpitem = 'Course_User_Logs';
-        }
-        push (@{$brcrum},
-                 {href => '/adm/createuser?action=changelogs',
-                  text => 'User Management Logs',
-                  help => $helpitem});
-        $bread_crumbs_component = 'User Changes';
-        $args = { bread_crumbs           => $brcrum,
-                  bread_crumbs_component => $bread_crumbs_component};
-        $r->print(&header(undef,$args));
-        &print_userchangelogs_display($r,$context,$permission);
+        &print_userchangelogs_display($r,$context,$permission,$brcrum);
     } else {
         $bread_crumbs_component = 'User Management';
         $args = { bread_crumbs           => $brcrum,
@@ -5352,8 +5346,18 @@
          {categorytitle => 'Administration',
          items => [ ]},
        );
-            
+
     if ($context eq 'domain'){
+        push(@{  $menu[0]->{items} }, # Single Users
+            {
+             linktext => 'User Access Log',
+             icon => 'document-properties.png',
+             #help => 'User_Access_Logs',
+             url => '/adm/createuser?action=accesslogs',
+             permission => $permission->{'activity'},
+             linktitle => 'View user access log.',
+            }
+        );
         
         push(@{ $menu[2]->{items} }, #Category: Administration
             {
@@ -6409,7 +6413,7 @@
 }
 
 sub print_userchangelogs_display {
-    my ($r,$context,$permission) = @_;
+    my ($r,$context,$permission,$brcrum) = @_;
     my $formname = 'rolelog';
     my ($username,$domain,$crstype,%roleslog);
     if ($context eq 'domain') {
@@ -6439,6 +6443,32 @@
     }
     if ((keys(%roleslog))[0]=~/^error\:/) { undef(%roleslog); }
 
+    my $helpitem;
+    if ($context eq 'course') {
+        $helpitem = 'Course_User_Logs';
+    }
+    push (@{$brcrum},
+             {href => '/adm/createuser?action=changelogs',
+              text => 'User Management Logs',
+              help => $helpitem});
+    my $bread_crumbs_component = 'User Changes';
+    my $args = { bread_crumbs           => $brcrum,
+                 bread_crumbs_component => $bread_crumbs_component};
+
+    # Create navigation javascript
+    my $jsnav = &userlogdisplay_js($formname);
+
+    my $jscript = (<<ENDSCRIPT);
+<script type="text/javascript">
+// <![CDATA[
+$jsnav
+// ]]>
+</script>
+ENDSCRIPT
+
+    # print page header
+    $r->print(&header($jscript,$args));
+
     # set defaults
     my $now = time();
     my $defstart = $now - (7*24*3600); #7 days ago 
@@ -6471,7 +6501,9 @@
     my ($minshown,$maxshown);
     $minshown = 1;
     my $count = 0;
-    if ($curr{'show'} ne &mt('all')) { 
+    if ($curr{'show'} =~ /\D/) {
+        $curr{'page'} = 1;
+    } else {
         $maxshown = $curr{'page'} * $curr{'show'};
         if ($curr{'page'} > 1) {
             $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'};
@@ -6483,8 +6515,6 @@
               &role_display_filter($context,$formname,$domain,$username,\%curr,
                                    $version,$crstype));
 
-    # Create navigation
-    my ($nav_script,$nav_links) = &userlogdisplay_nav($formname,\%curr,$more_records);
     my $showntableheader = 0;
 
     # Table Header
@@ -6509,7 +6539,7 @@
     foreach my $id (sort { $roleslog{$b}{'exe_time'}<=>$roleslog{$a}{'exe_time'} } (keys(%roleslog))) {
         next if (($roleslog{$id}{'exe_time'} < $curr{'rolelog_start_date'}) ||
                  ($roleslog{$id}{'exe_time'} > $curr{'rolelog_end_date'}));
-        if ($curr{'show'} ne &mt('all')) {
+        if ($curr{'show'} !~ /\D/) {
             if ($count >= $curr{'page'} * $curr{'show'}) {
                 $more_records = 1;
                 last;
@@ -6528,9 +6558,7 @@
         $count ++;
         next if ($count < $minshown);
         unless ($showntableheader) {
-            $r->print($nav_script
-                     .$nav_links
-                     .&Apache::loncommon::start_data_table()
+            $r->print(&Apache::loncommon::start_data_table()
                      .$tableheader);
             $r->rflush();
             $showntableheader = 1;
@@ -6591,8 +6619,8 @@
     }
 
     if ($showntableheader) { # Table footer, if content displayed above
-        $r->print(&Apache::loncommon::end_data_table()
-                 .$nav_links);
+        $r->print(&Apache::loncommon::end_data_table().
+                  &userlogdisplay_navlinks(\%curr,$more_records));
     } else { # No content displayed above
         $r->print('<p class="LC_info">'
                  .&mt('There are no records to display.')
@@ -6608,15 +6636,328 @@
     return;
 }
 
-sub userlogdisplay_nav {
-    my ($formname,$curr,$more_records) = @_;
-    my ($nav_script,$nav_links);
-    if (ref($curr) eq 'HASH') {
-        # Create Navigation:
-        # Navigation Script
-        $nav_script = <<"ENDSCRIPT";
+sub print_useraccesslogs_display {
+    my ($r,$uname,$udom,$permission,$brcrum) = @_;
+    my $formname = 'accesslog';
+    my $form = 'document.accesslog';
+
+# set breadcrumbs
+    my %breadcrumb_text = &singleuser_breadcrumb();
+    push (@{$brcrum},
+        {href => "javascript:backPage($form)",
+         text => $breadcrumb_text{'search'}});
+    my (@prevphases,$prevphasestr);
+    if ($env{'form.prevphases'}) {
+        @prevphases = split(/,/,$env{'form.prevphases'});
+        $prevphasestr = $env{'form.prevphases'};
+    }
+    if (($env{'form.phase'} eq 'userpicked') || (grep(/^userpicked$/, at prevphases))) {
+        push(@{$brcrum},
+              {href => "javascript:backPage($form,'get_user_info','select')",
+               text => $breadcrumb_text{'userpicked'}});
+        if ($env{'form.phase'} eq 'userpicked') {
+            $prevphasestr = 'userpicked';
+        }
+    }
+    push(@{$brcrum},
+             {href => '/adm/createuser?action=accesslogs',
+              text => 'User access logs',
+              help => 'User_Access_Logs'});
+    my $bread_crumbs_component = 'User Access Logs';
+    my $args = { bread_crumbs           => $brcrum,
+                 bread_crumbs_component => 'User Management'};
+
+# set javascript
+    my ($jsback,$elements) = &crumb_utilities();
+    my $jsnav = &userlogdisplay_js($formname);
+
+    my $jscript = (<<ENDSCRIPT);
 <script type="text/javascript">
 // <![CDATA[
+
+$jsback
+$jsnav
+
+// ]]>
+</script>
+
+ENDSCRIPT
+
+# print page header
+    $r->print(&header($jscript,$args));
+
+# early out unless log data can be displayed.
+    unless ($permission->{'activity'}) {
+        $r->print('<p class="LC_warning">'
+                 .&mt('You do not have rights to display user access logs.')
+                 .'</p>'
+                 .&earlyout_accesslog_form($formname,$prevphasestr,$udom));
+        return;
+    }
+
+    unless ($udom eq $env{'request.role.domain'}) {
+        $r->print('<p class="LC_warning">'
+                 .&mt("User's domain must match role's domain")
+                 .'</p>'
+                 .&earlyout_accesslog_form($formname,$prevphasestr,$udom));
+        return;
+    }
+
+    if (($uname eq '') || ($udom eq '')) {
+        $r->print('<p class="LC_warning">'
+                 .&mt('Invalid username or domain')
+                 .'</p>'
+                 .&earlyout_accesslog_form($formname,$prevphasestr,$udom));
+        return;
+    }
+
+# set defaults
+    my $now = time();
+    my $defstart = $now - (7*24*3600);
+    my %defaults = (
+                     page                 => '1',
+                     show                 => '10',
+                     activity             => 'any',
+                     accesslog_start_date => $defstart,
+                     accesslog_end_date   => $now,
+                   );
+    my $more_records = 0;
+
+# set current
+    my %curr;
+    foreach my $item ('show','page','activity') {
+        $curr{$item} = $env{'form.'.$item};
+    }
+    my ($startdate,$enddate) =
+        &Apache::lonuserutils::get_dates_from_form('accesslog_start_date','accesslog_end_date');
+    $curr{'accesslog_start_date'} = $startdate;
+    $curr{'accesslog_end_date'} = $enddate;
+    foreach my $key (keys(%defaults)) {
+        if ($curr{$key} eq '') {
+            $curr{$key} = $defaults{$key};
+        }
+    }
+    my ($minshown,$maxshown);
+    $minshown = 1;
+    my $count = 0;
+    if ($curr{'show'} =~ /\D/) {
+        $curr{'page'} = 1;
+    } else {
+        $maxshown = $curr{'page'} * $curr{'show'};
+        if ($curr{'page'} > 1) {
+            $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'};
+        }
+    }
+
+# form header
+    $r->print('<form action="/adm/createuser" method="post" name="'.$formname.'">'.
+              &activity_display_filter($formname,\%curr));
+
+    my $showntableheader = 0;
+    my ($nav_script,$nav_links);
+
+# table header
+    my $tableheader =
+        &Apache::loncommon::start_data_table_header_row()
+       .'<th> </th>'
+       .'<th>'.&mt('When').'</th>'
+       .'<th>'.&mt('HostID').'</th>'
+       .'<th>'.&mt('Event').'</th>'
+       .'<th>'.&mt('Other data').'</th>'
+       .&Apache::loncommon::end_data_table_header_row();
+
+    my %filters=(
+        start  => $curr{'accesslog_start_date'},
+        end    => $curr{'accesslog_end_date'},
+        action => $curr{'activity'},
+    );
+
+    my $reply = &Apache::lonnet::userlog_query($uname,$udom,%filters);
+    unless ( ($reply =~/^timeout/) || ($reply =~/^error/) ) {
+        my (%courses,%missing);
+        my @results = split(/\&/,$reply);
+        foreach my $item (reverse(@results)) {
+            my ($timestamp,$host,$event) = split(/:/,$item);
+            next unless ($event =~ /^(Log|Role)/);
+            if ($curr{'show'} !~ /\D/) {
+                if ($count >= $curr{'page'} * $curr{'show'}) {
+                    $more_records = 1;
+                    last;
+                }
+            }
+            $count ++;
+            next if ($count < $minshown);
+            unless ($showntableheader) {
+                $r->print($nav_script
+                         .&Apache::loncommon::start_data_table()
+                         .$tableheader);
+                $r->rflush();
+                $showntableheader = 1;
+            }
+            my ($shown,$extra,);
+            my ($event,$data) = split(/\s+/,&unescape($event));
+            if ($event eq 'Role') {
+                my ($rolecode,$extent) = split(/\./,$data,2);
+                next if ($extent eq '');
+                my ($crstype,$desc,$info);
+                if ($extent =~ m{^/($match_domain)/($match_courseid)$}) {
+                    my ($cdom,$cnum) = ($1,$2);
+                    my $cid = $cdom.'_'.$cnum;
+                    if (exists($courses{$cid})) {
+                        $crstype = $courses{$cid}{'type'};
+                        $desc = $courses{$cid}{'description'};
+                    } elsif ($missing{$cid}) {
+                        $crstype = 'Course';
+                        $desc = 'Course/Community';
+                    } else {
+                        my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.');
+                        if (ref($crsinfo{$cdom.'_'.$cnum}) eq 'HASH') {
+                            $courses{$cid} = $crsinfo{$cid};
+                            $crstype = $crsinfo{$cid}{'type'};
+                            $desc = $crsinfo{$cid}{'description'};
+                        } else {
+                            $missing{$cid} = 1;
+                        }
+                    }
+                    $extra = &mt($crstype).': <a href="/public/'.$cdom.'/'.$cnum.'/syllabus">'.$desc.'</a>';
+                } elsif ($extent =~ m{^/($match_domain)/($match_username|$)}) {
+                    my ($dom,$name) = ($1,$2);
+                    if ($rolecode eq 'au') {
+                        $extra = '';
+                    } elsif ($rolecode =~ /^(ca|aa)$/) {
+                        $extra = &mt('Authoring Space: [_1]',$name.':'.$dom);
+                    } elsif ($rolecode =~ /^(li|dg|dh|dc|sc)$/) {
+                        $extra = &mt('Domain: [_1]',$dom);
+                    }
+                }
+                my $rolename;
+                if ($rolecode =~ m{^cr/($match_domain)/($match_username)/(\w+)}) {
+                    my $role = $3;
+                    my $owner = "($2:$1)";
+                    if ($2 eq $1.'-domainconfig') {
+                        $owner = '(ad hoc)';
+                    }
+                    $rolename = &mt('Custom role: [_1]',$role.' '.$owner);
+                } else {
+                    $rolename = &Apache::lonnet::plaintext($rolecode,$crstype);
+                }
+                $shown = &mt('Role selection: [_1]',$rolename);
+            } else {
+                $shown = &mt($event);
+                if ($data ne '') {
+                   $extra = &mt('Client IP address: [_1]',$data);
+                }
+            }
+            $r->print(
+            &Apache::loncommon::start_data_table_row()
+           .'<td>'.$count.'</td>'
+           .'<td>'.&Apache::lonlocal::locallocaltime($timestamp).'</td>'
+           .'<td>'.$host.'</td>'
+           .'<td>'.$shown.'</td>'
+           .'<td>'.$extra.'</td>'
+           .&Apache::loncommon::end_data_table_row()."\n");
+        }
+    }
+
+    if ($showntableheader) { # Table footer, if content displayed above
+        $r->print(&Apache::loncommon::end_data_table().
+                  &userlogdisplay_navlinks(\%curr,$more_records));
+    } else { # No content displayed above
+        $r->print('<p class="LC_info">'
+                 .&mt('There are no records to display.')
+                 .'</p>');
+    }
+
+    # Form Footer
+    $r->print(
+        '<input type="hidden" name="currstate" value="" />'
+       .'<input type="hidden" name="accessuname" value="'.$uname.'" />'
+       .'<input type="hidden" name="accessudom" value="'.$udom.'" />'
+       .'<input type="hidden" name="page" value="'.$curr{'page'}.'" />'
+       .'<input type="hidden" name="prevphases" value="'.$prevphasestr.'" />'
+       .'<input type="hidden" name="phase" value="activity" />'
+       .'<input type="hidden" name="action" value="accesslogs" />'
+       .'<input type="hidden" name="srchdomain" value="'.$udom.'" />'
+       .'<input type="hidden" name="srchby" value="'.$env{'form.srchby'}.'" />'
+       .'<input type="hidden" name="srchtype" value="'.$env{'form.srchtype'}.'" />'
+       .'<input type="hidden" name="srchterm" value="'.&HTML::Entities::encode($env{'form.srchterm'},'<>"&').'" />'
+       .'<input type="hidden" name="srchin" value="'.$env{'form.srchin'}.'" />'
+       .'</form>');
+    return;
+}
+
+sub earlyout_accesslog_form {
+    my ($formname,$prevphasestr,$udom) = @_;
+    my $srchterm = &HTML::Entities::encode($env{'form.srchterm'},'<>"&');
+   return <<"END";
+<form action="/adm/createuser" method="post" name="$formname">
+<input type="hidden" name="currstate" value="" />
+<input type="hidden" name="prevphases" value="$prevphasestr" />
+<input type="hidden" name="phase" value="activity" />
+<input type="hidden" name="action" value="accesslogs" />
+<input type="hidden" name="srchdomain" value="$udom" />
+<input type="hidden" name="srchby" value="$env{'form.srchby'}" />
+<input type="hidden" name="srchtype" value="$env{'form.srchtype'}" />
+<input type="hidden" name="srchterm" value="$srchterm" />
+<input type="hidden" name="srchin" value="$env{'form.srchin'}" />
+</form>
+END
+}
+
+sub activity_display_filter {
+    my ($formname,$curr) = @_;
+    my $nolink = 1;
+    my $output = '<table><tr><td valign="top">'.
+                 '<span class="LC_nobreak"><b>'.&mt('Actions/page:').'</b></span><br />'.
+                 &Apache::lonmeta::selectbox('show',$curr->{'show'},undef,
+                                              (&mt('all'),5,10,20,50,100,1000,10000)).
+                 '</td><td>  </td>';
+    my $startform =
+        &Apache::lonhtmlcommon::date_setter($formname,'accesslog_start_date',
+                                            $curr->{'accesslog_start_date'},undef,
+                                            undef,undef,undef,undef,undef,undef,$nolink);
+    my $endform =
+        &Apache::lonhtmlcommon::date_setter($formname,'accesslog_end_date',
+                                            $curr->{'accesslog_end_date'},undef,
+                                            undef,undef,undef,undef,undef,undef,$nolink);
+    my %lt = &Apache::lonlocal::texthash (
+                                          activity => 'Activity',
+                                          Role     => 'Role selection',
+                                          log      => 'Log-in or Logout',
+    );
+    $output .= '<td valign="top"><b>'.&mt('Window during which actions occurred:').'</b><br />'.
+               '<table><tr><td>'.&mt('After:').
+               '</td><td>'.$startform.'</td></tr>'.
+               '<tr><td>'.&mt('Before:').'</td>'.
+               '<td>'.$endform.'</td></tr></table>'.
+               '</td>'.
+               '<td>  </td>'.
+               '<td valign="top"><b>'.&mt('Activities').'</b><br />'.
+               '<select name="activity"><option value="any"';
+    if ($curr->{'activity'} eq 'any') {
+        $output .= ' selected="selected"';
+    }
+    $output .= '>'.&mt('Any').'</option>'."\n";
+    foreach my $activity ('Role','log') {
+        my $selstr = '';
+        if ($activity eq $curr->{'activity'}) {
+            $selstr = ' selected="selected"';
+        }
+        $output .= '<option value="'.$activity.'"'.$selstr.'>'.$lt{$activity}.'</option>';
+    }
+    $output .= '</select></td>'.
+               '</tr></table>';
+    # Update Display button
+    $output .= '<p>'
+              .'<input type="submit" value="'.&mt('Update Display').'" />'
+              .'</p>';
+    return $output;
+}
+
+sub userlogdisplay_js {
+    my ($formname) = @_;
+    return <<"ENDSCRIPT";
+
 function chgPage(caller) {
     if (caller == 'previous') {
         document.$formname.page.value --;
@@ -6627,28 +6968,30 @@
     document.$formname.submit();
     return;
 }
-// ]]>
-</script>
 ENDSCRIPT
-        # Navigation Buttons
-        $nav_links = '<p>';
-        if (($curr->{'page'} > 1) || ($more_records)) {
-            if ($curr->{'page'} > 1) {
-                $nav_links .= '<input type="button"'
-                             .' onclick="javascript:chgPage('."'previous'".');"'
-                             .' value="'.&mt('Previous [_1] changes',$curr->{'show'})
-                             .'" /> ';
-            }
-            if ($more_records) {
-                $nav_links .= '<input type="button"'
-                             .' onclick="javascript:chgPage('."'next'".');"'
-                             .' value="'.&mt('Next [_1] changes',$curr->{'show'})
-                             .'" />';
-            }
+}
+
+sub userlogdisplay_navlinks {
+    my ($curr,$more_records) = @_;
+    return unless(ref($curr) eq 'HASH');
+    # Navigation Buttons
+    my $nav_links = '<p>';
+    if (($curr->{'page'} > 1) || ($more_records)) {
+        if (($curr->{'page'} > 1) && ($curr->{'show'} !~ /\D/)) {
+            $nav_links .= '<input type="button"'
+                         .' onclick="javascript:chgPage('."'previous'".');"'
+                         .' value="'.&mt('Previous [_1] changes',$curr->{'show'})
+                         .'" /> ';
+        }
+        if ($more_records) {
+            $nav_links .= '<input type="button"'
+                         .' onclick="javascript:chgPage('."'next'".');"'
+                         .' value="'.&mt('Next [_1] changes',$curr->{'show'})
+                         .'" />';
         }
-        $nav_links .= '</p>';
     }
-    return ($nav_script,$nav_links);
+    $nav_links .= '</p>';
+    return $nav_links;
 }
 
 sub role_display_filter {
@@ -6838,7 +7181,7 @@
             if ($domd_chk eq 'ok') {
                 $response .= &mt('You may want to search in the LON-CAPA domain instead of the institutional directory.');
             }
-            $response .= '<br /><br />';
+            $response .= '<br />';
         }
     } else {
         unless (($context eq 'requestcrs') && ($srch->{'srchtype'} eq 'exact')) {
@@ -6849,7 +7192,7 @@
                 if ($instd_chk eq 'ok') {
                     $response .= &mt('You may want to search in the institutional directory instead of the LON-CAPA domain.');
                 }
-                $response .= '<br /><br />';
+                $response .= '<br />';
             }
         }
     }
@@ -6880,6 +7223,9 @@
                                 &build_search_response($context,$srch,%srch_results);
                         } else {
                             $currstate = 'modify';
+                            if ($env{'form.action'} eq 'accesslogs') {
+                                $currstate = 'activity';
+                            }
                             my $uname = $srch->{'srchterm'};
                             my $udom = $srch->{'srchdomain'};
                             $srch_results{$uname.':'.$udom} =
@@ -6946,7 +7292,7 @@
                     &mt('Institutional directory search is not available in domain: [_1]',$showdom).
                     '</span><br />'.
                     &mt('You may want to search in the LON-CAPA domain instead of the institutional directory.').
-                    '<br /><br />'; 
+                    '<br />'; 
             }
         }
     } else {
@@ -7014,11 +7360,12 @@
                 ($currstate,$response,$forcenewuser) = 
                     &build_search_response($context,$srch,%srch_results);
             } else {
-                my $showdom = &display_domain_info($srch->{'srchdomain'});                $response = '<span class="LC_warning">'.
+                my $showdom = &display_domain_info($srch->{'srchdomain'});
+                $response = '<span class="LC_warning">'.
                     &mt('Institutional directory search is not available in domain: [_1]',$showdom).
                     '</span><br />'.
                     &mt('You may want to search in the LON-CAPA domain instead of the institutional directory.').
-                    '<br /><br />';
+                    '<br />';
             }
         }
     }
@@ -7166,7 +7513,11 @@
         $currstate = 'select';
     } else {
         if (keys(%srch_results) == 1) {
-            $currstate = 'modify';
+            if ($env{'form.action'} eq 'accesslogs') {
+                $currstate = 'activity';
+            } else {
+                $currstate = 'modify';
+            }
             $response = &mt("$single{$srch->{'srchtype'}} was found for the $names{$srch->{'srchby'}} ([_1]) in $names{$srch->{'srchin'}}.",$srch->{'srchterm'});
             if ($srch->{'srchin'} eq 'dom' || $srch->{'srchin'} eq 'instd') {
                 $response .= ': '.&display_domain_info($srch->{'srchdomain'});
@@ -7211,7 +7562,8 @@
                     $createdom = $env{'form.coursedom'};
                 }
             }
-            if (!($srch->{'srchby'} eq 'uname' && $srch->{'srchin'} eq 'dom' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchdomain'} eq $createdom)) {
+            unless (($env{'form.action'} eq 'accesslogs') || (($srch->{'srchby'} eq 'uname') && ($srch->{'srchin'} eq 'dom') &&
+                    ($srch->{'srchtype'} eq 'exact') && ($srch->{'srchdomain'} eq $createdom))) {
                 my $cancreate =
                     &Apache::lonuserutils::can_create_user($createdom,$context);
                 my $targetdom = '<span class="LC_cusr_emph">'.$createdom.'</span>';
@@ -7246,7 +7598,7 @@
                                  .&mt('Please contact the [_1]helpdesk[_2] if you need to create a new user.'
                                     ,' <a'.$helplink.'>'
                                     ,'</a>')
-                                 .'<br /><br />';
+                                 .'<br />';
                 }
             }
         }


More information about the LON-CAPA-cvs mailing list