# The LearningOnline Network with CAPA
# Utility functions for managing LON-CAPA user accounts
#
# $Id: lonuserutils.pm,v 1.10 2007/12/05 19:11:37 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/
#
#
###############################################################
###############################################################
package Apache::lonuserutils;
use strict;
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonlocal;
use Apache::longroup;
use LONCAPA qw(:DEFAULT :match);
###############################################################
###############################################################
# Drop student from all sections of a course, except optional $csec
sub modifystudent {
my ($udom,$unam,$courseid,$csec,$desiredhost)=@_;
# if $csec is undefined, drop the student from all the courses matching
# this one. If $csec is defined, drop them from all other sections of
# this course and add them to section $csec
my $cdom = $env{'course.'.$courseid.'.domain'};
my $cnum = $env{'course.'.$courseid.'.num'};
my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
my ($tmp) = keys(%roles);
# Bail out if we were unable to get the students roles
return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
# Go through the roles looking for enrollment in this course
my $result = '';
foreach my $course (keys(%roles)) {
if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) {
# We are in this course
my $section=$1;
$section='' if ($course eq "/$cdom/$cnum".'_st');
if (defined($csec) && $section eq $csec) {
$result .= 'ok:';
} elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
my (undef,$end,$start)=split(/\_/,$roles{$course});
my $now=time;
# if this is an active role
if (!($start && ($now<$start)) || !($end && ($now>$end))) {
my $reply=&Apache::lonnet::modifystudent
# dom name id mode pass f m l g
($udom,$unam,'', '', '',undef,undef,undef,undef,
$section,time,undef,undef,$desiredhost);
$result .= $reply.':';
}
}
}
}
if ($result eq '') {
$result = 'Unable to find section for this student';
} else {
$result =~ s/(ok:)+/ok/g;
}
return $result;
}
sub modifyuserrole {
my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass,
$first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role,
$end,$start,$checkid) = @_;
my ($scope,$userresult,$authresult,$roleresult,$idresult);
if ($setting eq 'course' || $context eq 'course') {
$scope = '/'.$cid;
$scope =~ s/\_/\//g;
if ($role ne 'cc' && $sec ne '') {
$scope .='/'.$sec;
}
} elsif ($context eq 'domain') {
$scope = '/'.$env{'request.role.domain'}.'/';
} elsif ($context eq 'construction_space') {
$scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
}
if ($context eq 'domain') {
my $uhome = &Apache::lonnet::homeserver($uname,$udom);
if ($uhome ne 'no_host') {
if (($changeauth eq 'Yes') && (&Apache::lonnet::allowed('mau',$udom))) {
if ((($umode =~ /^krb4|krb5|internal$/) && $upass ne '') ||
($umode eq 'localauth')) {
$authresult = &Apache::lonnet::modifyuserauth($udom,$uname,$umode,$upass);
}
}
if (($forceid) && (&Apache::lonnet::allowed('mau',$udom)) &&
($env{'form.recurseid'}) && ($checkid)) {
my %userupdate = (
lastname => $last,
middlename => $middle,
firstname => $first,
generation => $gene,
id => $uid,
);
$idresult = &propagate_id_change($uname,$udom,\%userupdate);
}
}
}
$userresult =
&Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first,
$middle,$last,$gene,$forceid,$desiredhome,
$email,$role,$start,$end);
if ($userresult eq 'ok') {
if ($role ne '') {
$roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope,
$role,$end,$start);
}
}
return ($userresult,$authresult,$roleresult,$idresult);
}
sub propagate_id_change {
my ($uname,$udom,$user) = @_;
my (@types,@roles,@cdoms);
@types = ('active','future');
@roles = ('st');
my $idresult;
my %roleshash = &Apache::lonnet::get_my_roles($uname,
$udom,'userroles',\@types,\@roles,\@cdoms);
foreach my $item (keys(%roleshash)) {
my ($cnum,$cdom,$role) = split(/:/,$item);
my ($start,$end) = split(/:/,$roleshash{$item});
if (&Apache::lonnet::is_course($cdom,$cnum)) {
my %userupdate;
my $result = &update_classlist($cdom,$cnum,$udom,$uname,\%userupdate);
if ($result eq 'ok') {
$idresult .= "Classlist change: $uname:$udom - class -> $cnum:$cdom\n";
} else {
$idresult .= "Error - $result -during classlist update for $uname:$udom in $cnum:$cdom\n";
}
}
}
return $idresult;
}
sub update_classlist {
my ($cdom,$cnum,$udom,$uname,$user) = @_;
my ($uid,$classlistentry);
my $fullname =
&Apache::lonnet::format_name($user->{'firstname'},$user->{'middlename'},
$user->{'lastname'},$user->{'generation'},
'lastname');
my %classhash = &Apache::lonnet::get('classlist',[$uname.':'.$udom],
$cdom,$cnum);
my @classinfo = split(/:/,$classhash{$uname.':'.$udom});
my $ididx=&Apache::loncoursedata::CL_ID() - 2;
my $nameidx=&Apache::loncoursedata::CL_FULLNAME() - 2;
for (my $i=0; $i<@classinfo; $i++) {
if ($i == $ididx) {
if (defined($user->{'id'})) {
$classlistentry .= $user->{'id'}.':';
} else {
$classlistentry .= $classinfo[$i].':';
}
} elsif ($i == $nameidx) {
$classlistentry .= $fullname.':';
} else {
$classlistentry .= $classinfo[$i].':';
}
}
$classlistentry =~ s/:$//;
my $reply=&Apache::lonnet::cput('classlist',
{"$uname:$udom" => $classlistentry},
$cdom,$cnum);
if (($reply eq 'ok') || ($reply eq 'delayed')) {
return 'ok';
} else {
return 'error: '.$reply;
}
}
###############################################################
###############################################################
# build a role type and role selection form
sub domain_roles_select {
# Set up the role type and role selection boxes when in
# domain context
#
# Role types
my @roletypes = ('domain','construction_space','course');
my %lt = &role_type_names();
#
# build up the menu information to be passed to
# &Apache::loncommon::linked_select_forms
my %select_menus;
if ($env{'form.roletype'} eq '') {
$env{'form.roletype'} = 'domain';
}
foreach my $roletype (@roletypes) {
# set up the text for this domain
$select_menus{$roletype}->{'text'}= $lt{$roletype};
# we want a choice of 'default' as the default in the second menu
if ($env{'form.roletype'} ne '') {
$select_menus{$roletype}->{'default'} = $env{'form.showrole'};
} else {
$select_menus{$roletype}->{'default'} = 'Any';
}
# Now build up the other items in the second menu
my @roles;
if ($roletype eq 'domain') {
@roles = &domain_roles();
} elsif ($roletype eq 'construction_space') {
@roles = &construction_space_roles();
} else {
@roles = &course_roles('domain');
unshift(@roles,'cr');
}
my $order = ['Any',@roles];
$select_menus{$roletype}->{'order'} = $order;
foreach my $role (@roles) {
if ($role eq 'cr') {
$select_menus{$roletype}->{'select2'}->{$role} =
&mt('Custom role');
} else {
$select_menus{$roletype}->{'select2'}->{$role} =
&Apache::lonnet::plaintext($role);
}
}
$select_menus{$roletype}->{'select2'}->{'Any'} = &mt('Any');
}
my $result = &Apache::loncommon::linked_select_forms
('studentform',(' 'x3).&mt('Role: '),$env{'form.roletype'},
'roletype','showrole',\%select_menus,['domain','construction_space','course']);
return $result;
}
###############################################################
###############################################################
sub hidden_input {
my ($name,$value) = @_;
return ''."\n";
}
sub print_upload_manager_header {
my ($r,$datatoken,$distotal,$krbdefdom,$context)=@_;
my $javascript;
#
if (! exists($env{'form.upfile_associate'})) {
$env{'form.upfile_associate'} = 'forward';
}
if ($env{'form.associate'} eq 'Reverse Association') {
if ( $env{'form.upfile_associate'} ne 'reverse' ) {
$env{'form.upfile_associate'} = 'reverse';
} else {
$env{'form.upfile_associate'} = 'forward';
}
}
if ($env{'form.upfile_associate'} eq 'reverse') {
$javascript=&upload_manager_javascript_reverse_associate();
} else {
$javascript=&upload_manager_javascript_forward_associate();
}
#
# Deal with restored settings
my $password_choice = '';
if (exists($env{'form.ipwd_choice'}) &&
$env{'form.ipwd_choice'} ne '') {
# If a column was specified for password, assume it is for an
# internal password. This is a bug waiting to be filed (could be
# local or krb auth instead of internal) but I do not have the
# time to mess around with this now.
$password_choice = 'int';
}
#
my $javascript_validations =
&javascript_validations('auth',$krbdefdom,$password_choice,undef,
$env{'request.role.domain'});
my $checked=(($env{'form.noFirstLine'})?' checked="checked" ':'');
$r->print(&mt('Total number of records found in file: [_1].',$distotal).
"
\n");
$r->print('
'.&mt('Change authentication for existing users to these settings?').'
'; } else { $Str .= "\n". &mt('Note: this will not take effect if the user already exists'). &Apache::loncommon::help_open_topic('Auth_Options'). "
\n"; } $Str .= &set_login($defdom,$krbform,$intform,$locform); my ($home_server_pick,$numlib) = &Apache::loncommon::home_server_form_item($defdom,'lcserver', 'default','hide'); if ($numlib > 1) { $Str .= '\n".$date_table."
\n"; if ($context eq 'domain') { $Str .= ''.&mt('role').': '. $options.' | '. ''.&mt('section').': |
\n".'
'."\n".
&mt('(only do if you know what you are doing.)')."
\n";
if ($context eq 'domain') {
$output .= '
';
my @linkdests = ('aboutme');
if ($permission->{'cusr'}) {
push (@linkdests,'modify');
$output .= ''.$lt{'link'}.': ';
my $usernamelink = $env{'form.usernamelink'};
if ($usernamelink eq '') {
$usernamelink = 'aboutme';
}
foreach my $item (@linkdests) {
my $checkedstr = '';
if ($item eq $usernamelink) {
$checkedstr = ' checked="checked" ';
}
$output .= ' ';
}
$output .= '
';
} else {
$output .= &mt("Click on a username to view the user's personal page.").'
';
}
}
$output .= "\n
\n". &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(); if ($mode eq 'autoenroll') { $output .= "
'. &mt('Your Excel spreadsheet').' '.&mt('is ready for download').'.
'."\n"); } elsif ($mode eq 'csv') { close($CSVfile); $r->print(''. &mt('Your CSV file').' is ready for download.'. "\n"); $r->rflush(); } if ($mode eq 'autoenroll') { return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount); } else { return ($usercount); } } sub print_username_link { my ($permission,$in) = @_; my $output; if (!$permission->{'cusr'}) { $output = &Apache::loncommon::aboutmewrapper($in->{'username'}, $in->{'username'}, $in->{'domain'}); } else { $output = '{'username'}','$in->{'domain'}'".')" />'. $in->{'username'}.''; } return $output; } sub role_type_names { my %lt = &Apache::lonlocal::texthash ( 'domain' => 'Domain Roles', 'construction_space' => 'Co-Author Roles', 'course' => 'Course Roles', ); return %lt; } sub results_header_row { my ($rolefilter,$statusmode,$context) = @_; my ($description,$showfilter); if ($rolefilter ne 'Any') { $showfilter = $rolefilter; } if ($context eq 'course') { $description = &mt('Course - ').$env{'course.'.$env{'request.course.id'}.'.description'}.': '; if ($statusmode eq 'Expired') { $description .= &mt('Users in course with expired [_1] roles',$showfilter); } if ($statusmode eq 'Future') { $description .= &mt('Users in course with future [_1] roles',$showfilter); } elsif ($statusmode eq 'Active') { $description .= &mt('Users in course with active [_1] roles',$showfilter); } else { if ($rolefilter eq 'Any') { $description .= &mt('All users in course'); } else { $description .= &mt('All users in course with [_1] roles',$rolefilter); } } } elsif ($context eq 'construction_space') { $description = &mt('Author space for [_1].').' '; if ($statusmode eq 'Expired') { $description .= &mt('Co-authors with expired [_1] roles',$showfilter); } elsif ($statusmode eq 'Future') { $description .= &mt('Co-authors with future [_1] roles',$showfilter); } elsif ($statusmode eq 'Active') { $description .= &mt('Co-authors with active [_1] roles',$showfilter); } else { if ($rolefilter eq 'Any') { $description .= &mt('All co-authors'); } else { $description .= &mt('All co-authors with [_1] roles',$rolefilter); } } } elsif ($context eq 'domain') { my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description'); $description = &mt('Domain - ').$domdesc.': '; if ($env{'form.roletype'} eq 'domain') { if ($statusmode eq 'Expired') { $description .= &mt('Users in domain with expired [_1] roles',$showfilter); } elsif ($statusmode eq 'Future') { $description .= &mt('Users in domain with future [_1] roles',$showfilter); } elsif ($statusmode eq 'Active') { $description .= &mt('Users in domain with active [_1] roles',$showfilter); } else { if ($rolefilter eq 'Any') { $description .= &mt('All users in domain'); } else { $description .= &mt('All users in domain with [_1] roles',$rolefilter); } } } elsif ($env{'form.roletype'} eq 'construction_space') { if ($statusmode eq 'Expired') { $description .= &mt('Co-authors in domain with expired [_1] roles',$showfilter); } elsif ($statusmode eq 'Future') { $description .= &mt('Co-authors in domain with future [_1] roles',$showfilter); } elsif ($statusmode eq 'Active') { $description .= &mt('Co-authors in domain with active [_1] roles',$showfilter); } else { if ($rolefilter eq 'Any') { $description .= &mt('All users with co-author roles in domain',$showfilter); } else { $description .= &mt('All co-authors in domain with [_1] roles',$rolefilter); } } } elsif ($env{'form.roletype'} eq 'course') { my $coursefilter = $env{'form.coursepick'}; if ($coursefilter eq 'category') { my $instcode = &instcode_from_coursefilter(); if ($instcode eq '.') { $description .= &mt('All courses in domain').' - '; } else { $description .= &mt('Courses in domain with institutional code: [_1]',$instcode).' - '; } } elsif ($coursefilter eq 'selected') { $description .= &mt('Selected courses in domain').' - '; } elsif ($coursefilter eq 'all') { $description .= &mt('All courses in domain').' - '; } if ($statusmode eq 'Expired') { $description .= &mt('users with expired [_1] roles',$showfilter); } elsif ($statusmode eq 'Future') { $description .= &mt('users with future [_1] roles',$showfilter); } elsif ($statusmode eq 'Active') { $description .= &mt('users with active [_1] roles',$showfilter); } else { if ($rolefilter eq 'Any') { $description .= &mt('all users'); } else { $description .= &mt('users with [_1] roles',$rolefilter); } } } } return $description; } ################################################# ################################################# sub show_drop_list { my ($r,$classlist,$keylist,$nosort)=@_; my $cid=$env{'request.course.id'}; if (! exists($env{'form.sortby'})) { &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['sortby']); } my $sortby = $env{'form.sortby'}; if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) { $sortby = 'username'; } my $cdom = $env{'course.'.$cid.'.domain'}; my $cnum = $env{'course.'.$cid,'.num'}; my ($classgroups) = &Apache::loncoursedata::get_group_memberships( $classlist,$keylist,$cdom,$cnum); # my $action = "drop"; $r->print(<
END
my %lt=&Apache::lonlocal::texthash('usrn' => "username",
'dom' => "domain",
'sn' => "student name",
'sec' => "section",
'start' => "start date",
'end' => "end date",
'groups' => "active groups",
);
if ($nosort) {
$r->print(&Apache::loncommon::start_data_table());
$r->print(<
$lt{'usrn'}
$lt{'dom'}
ID
$lt{'sn'}
$lt{'sec'}
$lt{'start'}
$lt{'end'}
$lt{'groups'}
END
} else {
$r->print(&Apache::loncommon::start_data_table());
$r->print(<
$lt{'usrn'}
$lt{'dom'}
ID
$lt{'sn'}
$lt{'sec'}
$lt{'start'}
$lt{'end'}
$lt{'groups'}
END
}
#
# Sort the students
my %index;
my $i;
foreach (@$keylist) {
$index{$_} = $i++;
}
$index{'groups'} = scalar(@$keylist);
my $index = $index{$sortby};
my $second = $index{'username'};
my $third = $index{'domain'};
my @Sorted_Students = sort {
lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
||
lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
||
lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
} (keys(%$classlist));
foreach my $student (@Sorted_Students) {
my $error;
my $sdata = $classlist->{$student};
my $username = $sdata->[$index{'username'}];
my $domain = $sdata->[$index{'domain'}];
my $section = $sdata->[$index{'section'}];
my $name = $sdata->[$index{'fullname'}];
my $id = $sdata->[$index{'id'}];
my $start = $sdata->[$index{'start'}];
my $end = $sdata->[$index{'end'}];
my $groups = $classgroups->{$student};
my $active_groups;
if (ref($groups->{active}) eq 'HASH') {
$active_groups = join(', ',keys(%{$groups->{'active'}}));
}
if (! defined($start) || $start == 0) {
$start = &mt('none');
} else {
$start = &Apache::lonlocal::locallocaltime($start);
}
if (! defined($end) || $end == 0) {
$end = &mt('none');
} else {
$end = &Apache::lonlocal::locallocaltime($end);
}
my $status = $sdata->[$index{'status'}];
next if ($status ne 'Active');
#
$r->print(&Apache::loncommon::start_data_table_row());
$r->print(<<"END");
$username
$domain
$id
$name
$section
$start
$end
$active_groups
END
$r->print(&Apache::loncommon::end_data_table_row());
}
$r->print(&Apache::loncommon::end_data_table().'
');
%lt=&Apache::lonlocal::texthash(
'dp' => "Expire Users' Roles",
'ca' => "check all",
'ua' => "uncheck all",
);
$r->print(<<"END");
END return; } # # Print out the initial form to get the file containing a list of users # sub print_first_users_upload_form { my ($r,$context) = @_; my $str; $str = ''; $str .= ''; $str .= ''; $str .= "
\n"; $str .= ''."\n"; $str .= '
\n"; $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List", &mt("How do I create a users list from a spreadsheet")). "\n"); } elsif ($context eq 'construction_space') { $r->print('
\n"); } else { $r->print('
\n");
}
my %counts = (
user => 0,
auth => 0,
role => 0,
);
my $flushc=0;
my %student=();
my %curr_groups;
my %userchg;
if ($context eq 'course') {
# Get information about course groups
%curr_groups = &Apache::longroup::coursegroups();
}
my (%curr_rules,%got_rules,%alerts);
# Get new users list
foreach (@userdata) {
my %entries=&Apache::loncommon::record_sep($_);
# Determine user name
unless (($entries{$fields{'username'}} eq '') ||
(!defined($entries{$fields{'username'}}))) {
my ($fname, $mname, $lname,$gen) = ('','','','');
if (defined($fields{'names'})) {
($lname,$fname,$mname)=($entries{$fields{'names'}}=~
/([^\,]+)\,\s*(\w+)\s*(.*)$/);
} else {
if (defined($fields{'fname'})) {
$fname=$entries{$fields{'fname'}};
}
if (defined($fields{'mname'})) {
$mname=$entries{$fields{'mname'}};
}
if (defined($fields{'lname'})) {
$lname=$entries{$fields{'lname'}};
}
if (defined($fields{'gen'})) {
$gen=$entries{$fields{'gen'}};
}
}
if ($entries{$fields{'username'}}
ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
$r->print('
'.
&mt('[_1]: Unacceptable username for user [_2] [_3] [_4] [_5]',
$entries{$fields{'username'}},$fname,$mname,$lname,$gen).
'');
} else {
my $username = $entries{$fields{'username'}};
my $sec;
if ($context eq 'course' || $setting eq 'course') {
# determine section number
if (defined($fields{'sec'})) {
if (defined($entries{$fields{'sec'}})) {
$sec=$entries{$fields{'sec'}};
}
} else {
$sec = $defaultsec;
}
# remove non alphanumeric values from section
$sec =~ s/\W//g;
if ($sec eq "none" || $sec eq 'all') {
$r->print('
'.
&mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a reserved word.',
$username,$sec,$fname,$mname,$lname,$gen));
next;
} elsif (($sec ne '') && (exists($curr_groups{$sec}))) {
$r->print('
'.
&mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a course group. Section names and group names must be distinct.',
$username,$sec,$fname,$mname,$lname,$gen));
next;
}
}
# determine id number
my $id='';
if (defined($fields{'id'})) {
if (defined($entries{$fields{'id'}})) {
$id=$entries{$fields{'id'}};
}
$id=~tr/A-Z/a-z/;
}
# determine email address
my $email='';
if (defined($fields{'email'})) {
if (defined($entries{$fields{'email'}})) {
$email=$entries{$fields{'email'}};
unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; } }
}
# determine user password
my $password = $genpwd;
if (defined($fields{'ipwd'})) {
if ($entries{$fields{'ipwd'}}) {
$password=$entries{$fields{'ipwd'}};
}
}
# determine user role
my $role = '';
if (defined($fields{'role'})) {
if ($entries{$fields{'role'}}) {
my @poss_roles =
&curr_role_permissions($context,$setting);
if (grep(/^\Q$entries{$fields{'role'}}\E/,@poss_roles)) {
$role=$entries{$fields{'role'}};
} else {
my $rolestr = join(', ',@poss_roles);
$r->print('
'.
&mt('[_1]: You do not have permission to add the requested role [_2] for the user.',$entries{$fields{'username'}},$entries{$fields{'role'}}).'
'.&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n");
next;
}
}
}
if ($role eq '') {
$role = $defaultrole;
}
# Clean up whitespace
foreach (\$domain,\$username,\$id,\$fname,\$mname,
\$lname,\$gen,\$sec,\$role) {
$$_ =~ s/(\s+$|^\s+)//g;
}
# check against rules
my $checkid = 0;
my $newuser = 0;
my (%rulematch,%inst_results,%idinst_results);
my $uhome=&Apache::lonnet::homeserver($username,$domain);
if ($uhome eq 'no_host') {
$checkid = 1;
$newuser = 1;
my $checkhash;
my $checks = { 'username' => 1 };
$checkhash->{$username.':'.$domain} = { 'newuser' => 1, };
&Apache::loncommon::user_rule_check($checkhash,$checks,
\%alerts,\%rulematch,\%inst_results,\%curr_rules,
\%got_rules);
if (ref($alerts{'username'}) eq 'HASH') {
if (ref($alerts{'username'}{$domain}) eq 'HASH') {
next if ($alerts{'username'}{$domain}{$username});
}
}
}
if ($id ne '') {
if (!$newuser) {
my %idhash = &Apache::lonnet::idrget($domain,($username));
if ($idhash{$username} ne $id) {
$checkid = 1;
}
}
if ($checkid) {
my $checkhash;
my $checks = { 'id' => 1 };
$checkhash->{$username.':'.$domain} = { 'newuser' => $newuser,
'id' => $id };
&Apache::loncommon::user_rule_check($checkhash,$checks,
\%alerts,\%rulematch,\%idinst_results,\%curr_rules,
\%got_rules);
if (ref($alerts{'id'}) eq 'HASH') {
if (ref($alerts{'id'}{$domain}) eq 'HASH') {
next if ($alerts{'id'}{$domain}{$id});
}
}
}
}
if ($password || $env{'form.login'} eq 'loc') {
my ($userresult,$authresult,$roleresult);
if ($role eq 'st') {
&modifystudent($domain,$username,$cid,$sec,
$desiredhost);
$roleresult =
&Apache::lonnet::modifystudent
($domain,$username,$id,$amode,$password,
$fname,$mname,$lname,$gen,$sec,$enddate,
$startdate,$env{'form.forceid'},
$desiredhost,$email);
} else {
($userresult,$authresult,$roleresult) =
&modifyuserrole($context,$setting,
$changeauth,$cid,$domain,$username,
$id,$amode,$password,$fname,
$mname,$lname,$gen,$sec,
$env{'form.forceid'},$desiredhost,
$email,$role,$enddate,$startdate,$checkid);
}
$flushc =
&user_change_result($r,$userresult,$authresult,
$roleresult,\%counts,$flushc,
$username,%userchg);
} else {
if ($context eq 'course') {
$r->print('
'.
&mt('[_1]: Unable to enroll. No password specified.',$username)
);
} elsif ($context eq 'construction_space') {
$r->print('
'.
&mt('[_1]: Unable to add co-author. No password specified.',$username)
);
} else {
$r->print('
'.
&mt('[_1]: Unable to add user. No password specified.',$username)
);
}
}
}
}
} # end of foreach (@userdata)
# Flush the course logs so reverse user roles immediately updated
&Apache::lonnet::flushcourselogs();
$r->print("
\n".&mt('Processed [_1] user(s).',$counts{'user'}). "
\n"); if ($counts{'role'} > 0) { $r->print("\n". &mt('Roles added for [_1] users. If user is active, the new role will be available when the user next logs in to LON-CAPA.',$counts{'role'})."
\n"); } if ($counts{'auth'} > 0) { $r->print("\n". &mt('Authentication changed for [_1] existing users.', $counts{'auth'})."
\n"); } if (keys(%alerts) > 0) { if (ref($alerts{'username'}) eq 'HASH') { foreach my $dom (sort(keys(%{$alerts{'username'}}))) { my $count; if (ref($alerts{'username'}{$dom}) eq 'HASH') { $count = keys(%{$alerts{'username'}{$dom}}); } my $domdesc = &Apache::lonnet::domain($domain,'description'); if (ref($curr_rules{$dom}) eq 'HASH') { $r->print(&Apache::loncommon::instrule_disallow_msg( 'username',$domdesc,$count,'upload')); } $r->print(&Apache::loncommon::user_rule_formats($dom, $domdesc,$curr_rules{$dom}{'username'}, 'username')); } } if (ref($alerts{'id'}) eq 'HASH') { foreach my $dom (sort(keys(%{$alerts{'id'}}))) { my $count; if (ref($alerts{'id'}{$dom}) eq 'HASH') { $count = keys(%{$alerts{'id'}{$dom}}); } my $domdesc = &Apache::lonnet::domain($domain,'description'); if (ref($curr_rules{$dom}) eq 'HASH') { $r->print(&Apache::loncommon::instrule_disallow_msg( 'id',$domdesc,$count,'upload')); } $r->print(&Apache::loncommon::user_rule_formats($dom, $domdesc,$curr_rules{$dom}{'id'},'id')); } } } $r->print(''); ##################################### # Drop students # ##################################### if ($env{'form.fullup'} eq 'yes') { $r->print(''.&mt('Dropped [_1] user(s).',$count).'
'); $r->print(''.&mt('Re-enrollment will re-activate data.')) if ($count);
}
sub classlist_drop {
my ($scope,$uname,$udom,$now,$action) = @_;
my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)});
my $cid=$cdom.'_'.$cnum;
my $user = $uname.':'.$udom;
if ($action eq 'drop') {
if (!&active_student_roles($cnum,$cdom,$uname,$udom)) {
my $result =
&Apache::lonnet::cput('classlist',
{ $user => $now },
$env{'course.'.$cid.'.domain'},
$env{'course.'.$cid.'.num'});
return &mt('Drop from classlist: [_1]',
''.$result.'').'
';
}
}
}
sub active_student_roles {
my ($cnum,$cdom,$uname,$udom) = @_;
my %roles =
&Apache::lonnet::get_my_roles($uname,$udom,'userroles',
['future','active'],['st']);
return exists($roles{"$cnum:$cdom:st"});
}
sub section_check_js {
my $groupslist= &get_groupslist();
return <<"END";
function validate(caller) {
var groups = new Array($groupslist);
var secname = caller.value;
if ((secname == 'all') || (secname == 'none')) {
alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name.");
return 'error';
}
if (secname != '') {
for (var k=0; k'.$authformint.' '.
&Apache::loncommon::end_data_table_row()."\n"
}
if ($can_assign{'loc'}) {
$response .= &Apache::loncommon::start_data_table_row().
''.$authformloc.' '.
&Apache::loncommon::end_data_table_row()."\n";
}
$response .= &Apache::loncommon::end_data_table();
}
return $response;
}
sub course_sections {
my ($sections_count,$role) = @_;
my $output = '';
my @sections = (sort {$a <=> $b} keys %{$sections_count});
if (scalar(@sections) == 1) {
$output = '