--- loncom/interface/loncreateuser.pm 2006/11/23 00:04:09 1.137 +++ loncom/interface/loncreateuser.pm 2010/10/11 14:36:04 1.352 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Create a user # -# $Id: loncreateuser.pm,v 1.137 2006/11/23 00:04:09 raeburn Exp $ +# $Id: loncreateuser.pm,v 1.352 2010/10/11 14:36:04 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -33,11 +33,13 @@ package Apache::loncreateuser; =head1 NAME -Apache::loncreateuser - handler to create users and custom roles +Apache::loncreateuser.pm =head1 SYNOPSIS -Apache::loncreateuser provides an Apache handler for creating users, + Handler to create users and custom roles + + Provides an Apache handler for creating users, editing their login parameters, roles, and removing roles, and also creating and assigning custom roles. @@ -49,13 +51,14 @@ In LON-CAPA, roles are actually collecti Assistant", "Course Coordinator", and other such roles are really just collection of privileges that are useful in many circumstances. -Creating custom roles can be done by the Domain Coordinator through -the Create User functionality. That screen will show all privileges -that can be assigned to users. For a complete list of privileges, -please see C. +Custom roles can be defined by a Domain Coordinator, Course Coordinator +or Community Coordinator via the Manage User functionality. +The custom role editor screen will show all privileges which can be +assigned to users. For a complete list of privileges, please see +C. -Custom role definitions are stored in the C file of the role -author. +Custom role definitions are stored in the C file of the creator +of the role. =cut @@ -65,11 +68,11 @@ use Apache::lonnet; use Apache::loncommon; use Apache::lonlocal; use Apache::longroup; -use lib '/home/httpd/lib/perl/'; -use LONCAPA; +use Apache::lonuserutils; +use Apache::loncoursequeueadmin; +use LONCAPA qw(:DEFAULT :match); my $loginscript; # piece of javascript used in two separate instances -my $generalrule; my $authformnop; my $authformkrb; my $authformint; @@ -77,120 +80,667 @@ my $authformfsys; my $authformloc; sub initialize_authen_forms { - my ($krbdefdom)=( $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/); - $krbdefdom= uc($krbdefdom); - my %param = ( formname => 'document.cu', - kerb_def_dom => $krbdefdom - ); -# no longer static due to configurable kerberos defaults -# $loginscript = &Apache::loncommon::authform_header(%param); - $generalrule = &Apache::loncommon::authform_authorwarning(%param); + my ($dom,$formname,$curr_authtype,$mode) = @_; + my ($krbdef,$krbdefdom) = &Apache::loncommon::get_kerberos_defaults($dom); + my %param = ( formname => $formname, + kerb_def_dom => $krbdefdom, + kerb_def_auth => $krbdef, + domain => $dom, + ); + my %abv_auth = &auth_abbrev(); + if ($curr_authtype =~ /^(krb4|krb5|internal|localauth|unix):(.*)$/) { + my $long_auth = $1; + my $curr_autharg = $2; + my %abv_auth = &auth_abbrev(); + $param{'curr_authtype'} = $abv_auth{$long_auth}; + if ($long_auth =~ /^krb(4|5)$/) { + $param{'curr_kerb_ver'} = $1; + $param{'curr_autharg'} = $curr_autharg; + } + if ($mode eq 'modifyuser') { + $param{'mode'} = $mode; + } + } + $loginscript = &Apache::loncommon::authform_header(%param); + $authformkrb = &Apache::loncommon::authform_kerberos(%param); $authformnop = &Apache::loncommon::authform_nochange(%param); -# no longer static due to configurable kerberos defaults -# $authformkrb = &Apache::loncommon::authform_kerberos(%param); $authformint = &Apache::loncommon::authform_internal(%param); $authformfsys = &Apache::loncommon::authform_filesystem(%param); $authformloc = &Apache::loncommon::authform_local(%param); } +sub auth_abbrev { + my %abv_auth = ( + krb5 => 'krb', + krb4 => 'krb', + internal => 'int', + localuth => 'loc', + unix => 'fsys', + ); + return %abv_auth; +} -# ======================================================= Existing Custom Roles +# ==================================================== -sub my_custom_roles { - my %returnhash=(); - my %rolehash=&Apache::lonnet::dump('roles'); - foreach my $key (keys %rolehash) { - if ($key=~/^rolesdef\_(\w+)$/) { - $returnhash{$1}=$1; - } +sub portfolio_quota { + my ($ccuname,$ccdomain) = @_; + my %lt = &Apache::lonlocal::texthash( + 'usrt' => "User Tools", + 'disk' => "Disk space allocated to user's portfolio files", + 'cuqu' => "Current quota", + 'cust' => "Custom quota", + 'defa' => "Default", + 'chqu' => "Change quota", + ); + my ($currquota,$quotatype,$inststatus,$defquota) = + &Apache::loncommon::get_user_quota($ccuname,$ccdomain); + my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($ccdomain); + my ($longinsttype,$showquota,$custom_on,$custom_off,$defaultinfo); + if ($inststatus ne '') { + if ($usertypes->{$inststatus} ne '') { + $longinsttype = $usertypes->{$inststatus}; + } + } + $custom_on = ' '; + $custom_off = ' checked="checked" '; + my $quota_javascript = <<"END_SCRIPT"; + +END_SCRIPT + if ($quotatype eq 'custom') { + $custom_on = $custom_off; + $custom_off = ' '; + $showquota = $currquota; + if ($longinsttype eq '') { + $defaultinfo = &mt('For this user, the default quota would be [_1]' + .' Mb.',$defquota); + } else { + $defaultinfo = &mt("For this user, the default quota would be [_1]". + " Mb, as determined by the user's institutional". + " affiliation ([_2]).",$defquota,$longinsttype); + } + } else { + if ($longinsttype eq '') { + $defaultinfo = &mt('For this user, the default quota is [_1]' + .' Mb.',$defquota); + } else { + $defaultinfo = &mt("For this user, the default quota of [_1]". + " Mb, is determined by the user's institutional". + " affiliation ([_2]).",$defquota,$longinsttype); + } + } -# ==================================================== Figure out author access - -sub authorpriv { - my ($auname,$audom)=@_; - unless ((&Apache::lonnet::allowed('cca',$audom.'/'.$auname)) - || (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; } - return 1; + my $output = $quota_javascript."\n". + '

'.$lt{'usrt'}.'

'."\n". + &Apache::loncommon::start_data_table(); + + if (&Apache::lonnet::allowed('mut',$ccdomain)) { + $output .= &build_tools_display($ccuname,$ccdomain,'tools'); + } + if (&Apache::lonnet::allowed('mpq',$ccdomain)) { + $output .= ''."\n". + ' '.$lt{'disk'}.''."\n". + ' '."\n". + &Apache::loncommon::start_data_table_row()."\n". + ' '.$lt{'cuqu'}.': '. + $currquota.' Mb.  '. + $defaultinfo.''."\n". + &Apache::loncommon::end_data_table_row()."\n". + &Apache::loncommon::start_data_table_row()."\n". + ' '.$lt{'chqu'}. + ':  '. + '  '. + ' Mb'."\n". + &Apache::loncommon::end_data_table_row()."\n"; + } + $output .= &Apache::loncommon::end_data_table(); + return $output; } -# ==================================================== +sub build_tools_display { + my ($ccuname,$ccdomain,$context) = @_; + my (@usertools,%userenv,$output,@options,%validations,%reqtitles,%reqdisplay, + $colspan,$isadv,%domconfig); + my %lt = &Apache::lonlocal::texthash ( + 'blog' => "Personal User Blog", + 'aboutme' => "Personal Information Page", + 'portfolio' => "Personal User Portfolio", + 'avai' => "Available", + 'cusa' => "availability", + 'chse' => "Change setting", + 'usde' => "Use default", + 'uscu' => "Use custom", + 'official' => 'Can request creation of official courses', + 'unofficial' => 'Can request creation of unofficial courses', + 'community' => 'Can request creation of communities', + ); + if ($context eq 'requestcourses') { + %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname, + 'requestcourses.official','requestcourses.unofficial', + 'requestcourses.community'); + @usertools = ('official','unofficial','community'); + @options =('norequest','approval','autolimit','validate'); + %validations = &Apache::lonnet::auto_courserequest_checks($ccdomain); + %reqtitles = &courserequest_titles(); + %reqdisplay = &courserequest_display(); + $colspan = ' colspan="2"'; + %domconfig = + &Apache::lonnet::get_dom('configuration',['requestcourses'],$ccdomain); + $isadv = &Apache::lonnet::is_advanced_user($ccuname,$ccdomain); + } else { + %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname, + 'tools.aboutme','tools.portfolio','tools.blog'); + @usertools = ('aboutme','blog','portfolio'); + } + foreach my $item (@usertools) { + my ($custom_access,$curr_access,$cust_on,$cust_off,$tool_on,$tool_off, + $currdisp,$custdisp,$custradio); + $cust_off = 'checked="checked" '; + $tool_on = 'checked="checked" '; + $curr_access = + &Apache::lonnet::usertools_access($ccuname,$ccdomain,$item,undef, + $context); + if ($userenv{$context.'.'.$item} ne '') { + $cust_on = ' checked="checked" '; + $cust_off = ''; + } + if ($context eq 'requestcourses') { + if ($userenv{$context.'.'.$item} eq '') { + $custom_access = &mt('Currently from default setting.'); + } else { + $custom_access = &mt('Currently from custom setting.'); + } + } else { + if ($userenv{$context.'.'.$item} eq '') { + $custom_access = + &mt('Availability determined currently from default setting.'); + if (!$curr_access) { + $tool_off = 'checked="checked" '; + $tool_on = ''; + } + } else { + $custom_access = + &mt('Availability determined currently from custom setting.'); + if ($userenv{$context.'.'.$item} == 0) { + $tool_off = 'checked="checked" '; + $tool_on = ''; + } + } + } + $output .= ' '."\n". + ' '.$lt{$item}.''."\n". + ' '."\n". + &Apache::loncommon::start_data_table_row()."\n"; + if ($context eq 'requestcourses') { + my ($curroption,$currlimit); + if ($userenv{$context.'.'.$item} ne '') { + $curroption = $userenv{$context.'.'.$item}; + } else { + my (@inststatuses); + $curroption = + &Apache::loncoursequeueadmin::get_processtype($ccuname,$ccdomain,$isadv,$ccdomain, + $item,\@inststatuses,\%domconfig); + } + if (!$curroption) { + $curroption = 'norequest'; + } + if ($curroption =~ /^autolimit=(\d*)$/) { + $currlimit = $1; + if ($currlimit eq '') { + $currdisp = &mt('Yes, automatic creation'); + } else { + $currdisp = &mt('Yes, up to [quant,_1,request]/user',$currlimit); + } + } else { + $currdisp = $reqdisplay{$curroption}; + } + $custdisp = ''; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{'_custom_'}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } elsif ($option eq 'autolimit') { + if ($curroption =~ /^autolimit/) { + $checked = ' checked="checked"'; + } + } + $custdisp .= ''; + } + $custdisp .= '
 '; + if ($option eq 'autolimit') { + $custdisp .= '
'. + $reqtitles{'unlimited'}; + } else { + $custdisp .= ''; + } + $custdisp .= '
'; + $custradio = ''.&mt('Custom setting').'
'.$custdisp; + } else { + $currdisp = ($curr_access?&mt('Yes'):&mt('No')); + $custdisp = ' '; + $custradio = (' 'x2).'--'.$lt{'cusa'}.': '.$custdisp. + ''; + } + $output .= ' '.$custom_access.(' 'x4). + $lt{'avai'}.': '.$currdisp.''."\n". + &Apache::loncommon::end_data_table_row()."\n". + &Apache::loncommon::start_data_table_row()."\n". + ' '. + $lt{'chse'}.': '.(' ' x3). + ''.$custradio.''. + &Apache::loncommon::end_data_table_row()."\n"; + } + return $output; +} -sub portfolio_quota { - my ($ccuname,$ccdomain) = @_; - my %lt = &Apache::lonlocal::texthash( - 'disk' => "Disk space allocated to user's portfolio files", +sub coursereq_externaluser { + my ($ccuname,$ccdomain,$cdom) = @_; + my (@usertools,@options,%validations,%userenv,$output); + my %lt = &Apache::lonlocal::texthash ( + 'official' => 'Can request creation of official courses', + 'unofficial' => 'Can request creation of unofficial courses', + 'community' => 'Can request creation of communities', ); - my $output = '

'.$lt{'disk'}.'

'. - ' Mb'; + + %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname, + 'reqcrsotherdom.official','reqcrsotherdom.unofficial', + 'reqcrsotherdom.community'); + @usertools = ('official','unofficial','community'); + @options = ('approval','validate','autolimit'); + %validations = &Apache::lonnet::auto_courserequest_checks($cdom); + my $optregex = join('|',@options); + my %reqtitles = &courserequest_titles(); + foreach my $item (@usertools) { + my ($curroption,$currlimit,$tooloff); + if ($userenv{'reqcrsotherdom.'.$item} ne '') { + my @curr = split(',',$userenv{'reqcrsotherdom.'.$item}); + foreach my $req (@curr) { + if ($req =~ /^\Q$cdom\E\:($optregex)=?(\d*)$/) { + $curroption = $1; + $currlimit = $2; + last; + } + } + if (!$curroption) { + $curroption = 'norequest'; + $tooloff = ' checked="checked"'; + } + } else { + $curroption = 'norequest'; + $tooloff = ' checked="checked"'; + } + $output.= &Apache::loncommon::start_data_table_row()."\n". + ' '.$lt{$item}.': '. + ''; + foreach my $option (@options) { + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{'_external_'}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } + $output .= ''; + } + $output .= '
'."\n". + ''; + if ($option eq 'autolimit') { + $output .= ' '. + '
'.$reqtitles{'unlimited'}; + } else { + $output .= ''; + } + $output .= '
'."\n". + &Apache::loncommon::end_data_table_row()."\n"; + } return $output; } +sub courserequest_titles { + my %titles = &Apache::lonlocal::texthash ( + official => 'Official', + unofficial => 'Unofficial', + community => 'Communities', + norequest => 'Not allowed', + approval => 'Approval by Dom. Coord.', + validate => 'With validation', + autolimit => 'Numerical limit', + unlimited => '(blank for unlimited)', + ); + return %titles; +} + +sub courserequest_display { + my %titles = &Apache::lonlocal::texthash ( + approval => 'Yes, need approval', + validate => 'Yes, with validation', + norequest => 'No', + ); + return %titles; +} + # =================================================================== Phase one sub print_username_entry_form { - my ($r) = @_; + my ($r,$context,$response,$srch,$forcenewuser,$crstype,$brcrum) = @_; my $defdom=$env{'request.role.domain'}; - my @domains = &Apache::loncommon::get_domains(); - my $domform = &Apache::loncommon::select_dom_form($defdom,'ccdomain'); - my $selscript=&Apache::loncommon::studentbrowser_javascript(); - my $start_page = - &Apache::loncommon::start_page('Create Users, Change User Privileges', - $selscript); + my $formtoset = 'crtuser'; + if (exists($env{'form.startrolename'})) { + $formtoset = 'docustom'; + $env{'form.rolename'} = $env{'form.startrolename'}; + } elsif ($env{'form.origform'} eq 'crtusername') { + $formtoset = $env{'form.origform'}; + } + + my ($jsback,$elements) = &crumb_utilities(); + + my $jscript = &Apache::loncommon::studentbrowser_javascript()."\n". + ''."\n"; + + my %existingroles=&Apache::lonuserutils::my_custom_roles($crstype); + if (($env{'form.action'} eq 'custom') && (keys(%existingroles) > 0) + && (&Apache::lonnet::allowed('mcr','/'))) { + $jscript .= &customrole_javascript(); + } + my $helpitem = 'Course_Change_Privileges'; + if ($env{'form.action'} eq 'custom') { + $helpitem = 'Course_Editing_Custom_Roles'; + } elsif ($env{'form.action'} eq 'singlestudent') { + $helpitem = 'Course_Add_Student'; + } + my %breadcrumb_text = &singleuser_breadcrumb($crstype); + if ($env{'form.action'} eq 'custom') { + push(@{$brcrum}, + {href=>"javascript:backPage(document.crtuser)", + text=>"Pick custom role", + help => $helpitem,} + ); + } else { + push (@{$brcrum}, + {href => "javascript:backPage(document.crtuser)", + text => $breadcrumb_text{'search'}, + help => $helpitem, + faq => 282, + bug => 'Instructor Interface',} + ); + } + my %loaditems = ( + 'onload' => "javascript:setFormElements(document.$formtoset)", + ); + my $args = {bread_crumbs => $brcrum, + bread_crumbs_component => 'User Management', + add_entries => \%loaditems,}; + $r->print(&Apache::loncommon::start_page('User Management',$jscript,$args)); - my $sellink=&Apache::loncommon::selectstudent_link - ('crtuser','ccuname','ccdomain'); - my %existingroles=&my_custom_roles(); - my $choice=&Apache::loncommon::select_form('make new role','rolename', - ('make new role' => 'Generate new role ...',%existingroles)); my %lt=&Apache::lonlocal::texthash( - 'siur' => "Set Individual User Roles", + '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', 'usr' => "Username", 'dom' => "Domain", - 'usrr' => "User Roles", - 'ecrp' => "Edit Custom Role Privileges", - 'nr' => "Name of Role", - 'cre' => "Custom Role Editor" + 'ecrp' => "Define or Edit Custom Role", + 'nr' => "role name", + 'cre' => "Next", ); - my $help = &Apache::loncommon::help_open_menu(undef,undef,282,'Instructor Interface'); - my $helpsiur=&Apache::loncommon::help_open_topic('Course_Change_Privileges'); - my $helpecpr=&Apache::loncommon::help_open_topic('Course_Editing_Custom_Roles'); - $r->print(<<"ENDDOCUMENT"); -$start_page + + if ($env{'form.action'} eq 'custom') { + if (&Apache::lonnet::allowed('mcr','/')) { + my $newroletext = &mt('Define new custom role:'); + $r->print('
'. + ''. + ''. + '

'.$lt{'ecrp'}.'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(). + ''); + if (keys(%existingroles) > 0) { + $r->print('
'); + } else { + $r->print('
'.$newroletext.''); + } + $r->print(''.$lt{'nr'}.'
'. + &Apache::loncommon::end_data_table_row()); + if (keys(%existingroles) > 0) { + $r->print(&Apache::loncommon::start_data_table_row().'
'. + ''. + '
'. + ''. + ''. + &Apache::loncommon::end_data_table_row()); + } + $r->print(&Apache::loncommon::end_data_table().'

'. + '

'. + '
'); + } + } else { + my $actiontext = $lt{'srad'}; + if ($env{'form.action'} eq 'singlestudent') { + if ($crstype eq 'Community') { + $actiontext = $lt{'srme'}; + } else { + $actiontext = $lt{'srst'}; + } + } + $r->print("

$actiontext

"); + if ($env{'form.origform'} ne 'crtusername') { + $r->print("\n".$response); + } + $r->print(&entry_form($defdom,$srch,$forcenewuser,$context,$response,$crstype)); + } +} + +sub customrole_javascript { + my $js = <<"END"; + +END + return $js; +} + +sub entry_form { + my ($dom,$srch,$forcenewuser,$context,$responsemsg,$crstype) = @_; + my %domconf = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom); + my ($usertype,$inexact); + if (ref($srch) eq 'HASH') { + if (($srch->{'srchin'} eq 'dom') && + ($srch->{'srchby'} eq 'uname') && + ($srch->{'srchtype'} eq 'exact') && + ($srch->{'srchdomain'} ne '') && + ($srch->{'srchterm'} ne '')) { + my ($rules,$ruleorder) = + &Apache::lonnet::inst_userrules($srch->{'srchdomain'},'username'); + $usertype = &Apache::lonuserutils::check_usertype($srch->{'srchdomain'},$srch->{'srchterm'},$rules); + } else { + $inexact = 1; + } + } + my $cancreate = + &Apache::lonuserutils::can_create_user($dom,$context,$usertype); + my $userpicker = + &Apache::loncommon::user_picker($dom,$srch,$forcenewuser, + 'document.crtuser',$cancreate,$usertype); + my $srchbutton = &mt('Search'); + if ($env{'form.action'} eq 'singlestudent') { + $srchbutton = &mt('Search and Enroll'); + } elsif ($cancreate && $responsemsg ne '' && $inexact) { + $srchbutton = &mt('Search or Add New User'); + } + my $output = <<"ENDBLOCK";
- -

$lt{siur}$helpsiur

+ + +$userpicker + +
+ENDBLOCK + if ($env{'form.phase'} eq '') { + my $defdom=$env{'request.role.domain'}; + my $domform = &Apache::loncommon::select_dom_form($defdom,'srchdomain'); + my %lt=&Apache::lonlocal::texthash( + 'enro' => 'Enroll one student', + 'enrm' => 'Enroll one member', + 'admo' => 'Add/modify a single user', + 'crea' => 'create new user if required', + 'uskn' => "username is known", + 'crnu' => 'Create a new user', + 'usr' => 'Username', + 'dom' => 'in domain', + 'enrl' => 'Enroll', + 'cram' => 'Create/Modify user', + ); + my $sellink=&Apache::loncommon::selectstudent_link('crtusername','srchterm','srchdomain'); + my ($title,$buttontext,$showresponse); + if ($env{'form.action'} eq 'singlestudent') { + if ($crstype eq 'Community') { + $title = $lt{'enrm'}; + } else { + $title = $lt{'enro'}; + } + $buttontext = $lt{'enrl'}; + } else { + $title = $lt{'admo'}; + $buttontext = $lt{'cram'}; + } + if ($cancreate) { + $title .= ' ('.$lt{'crea'}.')'; + } else { + $title .= ' ('.$lt{'uskn'}.')'; + } + if ($env{'form.origform'} eq 'crtusername') { + $showresponse = $responsemsg; + } + $output .= <<"ENDDOCUMENT"; +
+
+ + + + + + + +

$title

+$showresponse - + + + + + + +
$lt{usr}: -$sellink
-$lt{'dom'}:$domform
$lt{'usr'}: $lt{'dom'}:$domform $sellink  
-
ENDDOCUMENT - if (&Apache::lonnet::allowed('mcr','/')) { - $r->print(< - -

$lt{'ecrp'}$helpecpr

-$lt{'nr'}: $choice
- - -ENDCUSTOM } - $r->print(&Apache::loncommon::end_page()); + return $output; } - sub user_modification_js { my ($pjump_def,$dc_setcourse_code,$nondc_setsection_code,$groupslist)=@_; return < +// END } # =================================================================== Phase two -sub print_user_modification_page { - my $r=shift; - my $ccuname=$env{'form.ccuname'}; - my $ccdomain=$env{'form.ccdomain'}; - - $ccuname=~s/\W//g; - $ccdomain=~s/\W//g; - - unless (($ccuname) && ($ccdomain)) { - &print_username_entry_form($r); - return; - } - - my $defdom=$env{'request.role.domain'}; +sub print_user_selection_page { + my ($r,$response,$srch,$srch_results,$srcharray,$context,$opener_elements,$crstype,$brcrum) = @_; + my @fields = ('username','domain','lastname','firstname','permanentemail'); + my $sortby = $env{'form.sortby'}; + + if (!grep(/^\Q$sortby\E$/,@fields)) { + $sortby = 'lastname'; + } + + my ($jsback,$elements) = &crumb_utilities(); + + my $jscript = (< +// + +ENDSCRIPT - my %param = ( formname => 'document.cu', - kerb_def_dom => $krbdefdom, - kerb_def_auth => $krbdef + my %lt=&Apache::lonlocal::texthash( + 'usrch' => "User Search to add/modify roles", + 'stusrch' => "User Search to enroll student", + 'memsrch' => "User Search to enroll member", + '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", + 'username' => "username", + 'domain' => "domain", + 'lastname' => "last name", + 'firstname' => "first name", + 'permanentemail' => "permanent e-mail", + ); + if ($context eq 'requestcrs') { + $r->print('
'); + } else { + my %breadcrumb_text = &singleuser_breadcrumb($crstype); + my $helpitem; + if ($env{'form.action'} eq 'singleuser') { + $helpitem = 'Course_Change_Privileges'; + } elsif ($env{'form.action'} eq 'singlestudent') { + $helpitem = 'Course_Add_Student'; + } + push (@{$brcrum}, + {href => "javascript:backPage(document.usersrchform,'','')", + text => $breadcrumb_text{'search'}, + faq => 282, + bug => 'Instructor Interface',}, + {href => "javascript:backPage(document.usersrchform,'get_user_info','select')", + text => $breadcrumb_text{'userpicked'}, + faq => 282, + bug => 'Instructor Interface', + help => $helpitem} ); - $loginscript = &Apache::loncommon::authform_header(%param); - $authformkrb = &Apache::loncommon::authform_kerberos(%param); - - $ccuname=~s/\W//g; - $ccdomain=~s/\W//g; - my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition(); - my $dc_setcourse_code = ''; - my $nondc_setsection_code = ''; - - my %loaditem; - - my $groupslist; - my %curr_groups = &Apache::longroup::coursegroups(); - if (%curr_groups) { - $groupslist = join('","',sort(keys(%curr_groups))); - $groupslist = '"'.$groupslist.'"'; - } - - if ($env{'request.role'} =~ m-^dc\./(\w+)/$-) { - my $dcdom = $1; - $loaditem{'onload'} = "document.cu.coursedesc.value='';"; - my @rolevals = ('st','ta','ep','in','cc'); - my (@crsroles,@grproles); - for (my $i=0; $i<@rolevals; $i++) { - $crsroles[$i]=&Apache::lonnet::plaintext($rolevals[$i],'Course'); - $grproles[$i]=&Apache::lonnet::plaintext($rolevals[$i],'Group'); - } - my $rolevalslist = join('","',@rolevals); - my $crsrolenameslist = join('","',@crsroles); - my $grprolenameslist = join('","',@grproles); - my $pickcrsfirst = '<--'.&mt('Pick course first'); - my $pickgrpfirst = '<--'.&mt('Pick group first'); - $dc_setcourse_code = <<"ENDSCRIPT"; - function setCourse() { - var course = document.cu.dccourse.value; - if (course != "") { - if (document.cu.dcdomain.value != document.cu.origdom.value) { - alert("You must select a course in the current domain"); - return; - } - var userrole = document.cu.role.options[document.cu.role.selectedIndex].value - var section=""; - var numsections = 0; - var newsecs = new Array(); - for (var i=0; i 1)) { - alert("In each course, each user may only have one student role at a time. You had selected "+numsections+" sections.\\nPlease modify your selections so they include no more than one section.") - return; - } - for (var j=0; j 0)) { - alert("Section designations do not apply to Course Coordinator roles.\\nA course coordinator role will be added with access to all sections."); - section = ""; - } - var coursename = "_$dcdom"+"_"+course+"_"+userrole - var numcourse = getIndex(document.cu.dccourse); - if (numcourse == "-1") { - alert("There was a problem with your course selection"); - return + $r->print(&Apache::loncommon::start_page('User Management',$jscript,{bread_crumbs => $brcrum})); + if ($env{'form.action'} eq 'singleuser') { + $r->print("$lt{'usrch'}
"); + $r->print(&entry_form($srch->{'srchdomain'},$srch,undef,$context,undef,$crstype)); + $r->print('

'.$lt{'usel'}.'

'); + } elsif ($env{'form.action'} eq 'singlestudent') { + $r->print($jscript.""); + if ($crstype eq 'Community') { + $r->print($lt{'memsrch'}); + } else { + $r->print($lt{'stusrch'}); } - else { - document.cu.elements[numcourse].name = "act"+coursename; - var numnewsec = getIndex(document.cu.newsec); - if (numnewsec != "-1") { - document.cu.elements[numnewsec].name = "sec"+coursename; - document.cu.elements[numnewsec].value = section; - } - var numstart = getIndex(document.cu.start); - if (numstart != "-1") { - document.cu.elements[numstart].name = "start"+coursename; - } - var numend = getIndex(document.cu.end); - if (numend != "-1") { - document.cu.elements[numend].name = "end"+coursename - } + $r->print("
"); + $r->print(&entry_form($srch->{'srchdomain'},$srch,undef,$context,undef,$crstype)); + $r->print('

'); + if ($crstype eq 'Community') { + $r->print($lt{'memsel'}); + } else { + $r->print($lt{'stusel'}); } + $r->print('

'); } - document.cu.submit(); } - - function getIndex(caller) { - for (var i=0;iprint('
'. + &Apache::loncommon::start_data_table()."\n". + &Apache::loncommon::start_data_table_header_row()."\n". + ' '."\n"); + foreach my $field (@fields) { + $r->print(' '. + $lt{$field}.''."\n"); + } + $r->print(&Apache::loncommon::end_data_table_header_row()); + + my @sorted_users = sort { + lc($srch_results->{$a}->{$sortby}) cmp lc($srch_results->{$b}->{$sortby}) + || + lc($srch_results->{$a}->{lastname}) cmp lc($srch_results->{$b}->{lastname}) + || + lc($srch_results->{$a}->{firstname}) cmp lc($srch_results->{$b}->{firstname}) + || + lc($a) cmp lc($b) + } (keys(%$srch_results)); + + foreach my $user (@sorted_users) { + my ($uname,$udom) = split(/:/,$user); + my $onclick; + if ($context eq 'requestcrs') { + $onclick = + 'onclick="javascript:gochoose('."'$uname','$udom',". + "'$srch_results->{$user}->{firstname}',". + "'$srch_results->{$user}->{lastname}',". + "'$srch_results->{$user}->{permanentemail}'".');"'; + } else { + $onclick = + ' onclick="javascript:pickuser('."'".$uname."'".','."'".$udom."'".');"'; } - return -1; + $r->print(&Apache::loncommon::start_data_table_row(). + ''. + ''.$uname.''. + ''.$udom.''); + foreach my $field ('lastname','firstname','permanentemail') { + $r->print(''.$srch_results->{$user}->{$field}.''); + } + $r->print(&Apache::loncommon::end_data_table_row()); } - - function setType() { - var crstype = document.cu.crstype.options[document.cu.crstype.selectedIndex].value; - rolevals = new Array("$rolevalslist"); - if (crstype == 'Group') { - if (document.cu.currsec.options[0].text == "$pickcrsfirst") { - document.cu.currsec.options[0].text = "$pickgrpfirst"; - } - grprolenames = new Array("$grprolenameslist"); - for (var i=0; iprint(&Apache::loncommon::end_data_table().'

'); + if (ref($srcharray) eq 'ARRAY') { + foreach my $item (@{$srcharray}) { + $r->print(''."\n"); } } -ENDSCRIPT + $r->print(' '."\n". + ' '."\n". + ' '."\n". + ' '."\n". + ' '."\n". + ' '."\n"); + if ($context eq 'requestcrs') { + $r->print($opener_elements.'
'); } else { - $nondc_setsection_code = <<"ENDSECCODE"; - function setSections() { - var re1 = /^currsec_/; - var groups = new Array($groupslist); - for (var i=0;i 0) { - if (document.cu.elements[i+1].value != "" && document.cu.elements[i+1].value != null) { - sections = sections + "," + document.cu.elements[i+1].value; - } - } - else { - sections = document.cu.elements[i+1].value; - } - var newsecs = document.cu.elements[i+1].value; - var numsplit; - if (newsecs != null && newsecs != "") { - numsplit = newsecs.split(/,/g); - numsec = numsec + numsplit.length; - } - - if ((role == 'st') && (numsec > 1)) { - alert("In each course, each user may only have one student role at a time. You had selected "+numsec+" sections.\\nPlease modify your selections so they include no more than one section.") - return; - } - else if (numsplit != null) { - for (var j=0; jprint($response.''); + } +} + +sub print_user_query_page { + my ($r,$caller,$brcrum) = @_; +# FIXME - this is for a network-wide name search (similar to catalog search) +# To use frames with similar behavior to catalog/portfolio search. +# To be implemented. + return; +} + +sub print_user_modification_page { + my ($r,$ccuname,$ccdomain,$srch,$response,$context,$permission,$crstype,$brcrum) = @_; + if (($ccuname eq '') || ($ccdomain eq '')) { + my $usermsg = &mt('No username and/or domain provided.'); + $env{'form.phase'} = ''; + &print_username_entry_form($r,$context,$usermsg,'','',$crstype,$brcrum); + return; + } + my ($form,$formname); + if ($env{'form.action'} eq 'singlestudent') { + $form = 'document.enrollstudent'; + $formname = 'enrollstudent'; + } else { + $form = 'document.cu'; + $formname = 'cu'; + } + my %abv_auth = &auth_abbrev(); + my (%rulematch,%inst_results,$newuser,%alerts,%curr_rules,%got_rules); + my $uhome=&Apache::lonnet::homeserver($ccuname,$ccdomain); + if ($uhome eq 'no_host') { + my $usertype; + my ($rules,$ruleorder) = + &Apache::lonnet::inst_userrules($ccdomain,'username'); + $usertype = + &Apache::lonuserutils::check_usertype($ccdomain,$ccuname,$rules); + my $cancreate = + &Apache::lonuserutils::can_create_user($ccdomain,$context, + $usertype); + if (!$cancreate) { + my $helplink = 'javascript:helpMenu('."'display'".')'; + my %usertypetext = ( + official => 'institutional', + unofficial => 'non-institutional', + ); + my $response; + if ($env{'form.origform'} eq 'crtusername') { + $response = ''.&mt('No match found for the username [_1] in LON-CAPA domain: [_2]',''.$ccuname.'',$ccdomain). + '
'; + } + $response .= '

' + .&mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.") + .' ' + .&mt('Please contact the [_1]helpdesk[_2] for assistance.' + ,'','') + .'


'; + $env{'form.phase'} = ''; + &print_username_entry_form($r,$context,$response,undef,undef,$crstype,$brcrum); + return; + } + $newuser = 1; + my $checkhash; + my $checks = { 'username' => 1 }; + $checkhash->{$ccuname.':'.$ccdomain} = { 'newuser' => $newuser }; + &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'}{$ccdomain}) eq 'HASH') { + my $domdesc = + &Apache::lonnet::domain($ccdomain,'description'); + if ($alerts{'username'}{$ccdomain}{$ccuname}) { + my $userchkmsg; + if (ref($curr_rules{$ccdomain}) eq 'HASH') { + $userchkmsg = + &Apache::loncommon::instrule_disallow_msg('username', + $domdesc,1). + &Apache::loncommon::user_rule_formats($ccdomain, + $domdesc,$curr_rules{$ccdomain}{'username'}, + 'username'); } + $env{'form.phase'} = ''; + &print_username_entry_form($r,$context,$userchkmsg,undef,undef,$crstype,$brcrum); + return; } } } - document.cu.submit(); + } else { + $newuser = 0; } -ENDSECCODE + if ($response) { + $response = '
'.$response; } - my $js = &user_modification_js($pjump_def,$dc_setcourse_code, - $nondc_setsection_code,$groupslist); - my $start_page = - &Apache::loncommon::start_page('Create Users, Change User Privileges', - $js,{'add_entries' => \%loaditem,}); + + my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition(); + my $dc_setcourse_code = ''; + my $nondc_setsection_code = ''; + my %loaditem; + + my $groupslist = &Apache::lonuserutils::get_groupslist(); + + my $js = &validation_javascript($context,$ccdomain,$pjump_def, + $groupslist,$newuser,$formname,\%loaditem); + my %breadcrumb_text = &singleuser_breadcrumb($crstype); + my $helpitem = 'Course_Change_Privileges'; + if ($env{'form.action'} eq 'singlestudent') { + $helpitem = 'Course_Add_Student'; + } + push (@{$brcrum}, + {href => "javascript:backPage($form)", + text => $breadcrumb_text{'search'}, + faq => 282, + bug => 'Instructor Interface',}); + if ($env{'form.phase'} eq 'userpicked') { + push(@{$brcrum}, + {href => "javascript:backPage($form,'get_user_info','select')", + text => $breadcrumb_text{'userpicked'}, + faq => 282, + bug => 'Instructor Interface',}); + } + push(@{$brcrum}, + {href => "javascript:backPage($form,'$env{'form.phase'}','modify')", + text => $breadcrumb_text{'modify'}, + faq => 282, + bug => 'Instructor Interface', + help => $helpitem}); + my $args = {'add_entries' => \%loaditem, + 'bread_crumbs' => $brcrum, + 'bread_crumbs_component' => 'User Management'}; + if ($env{'form.popup'}) { + $args->{'no_nav_bar'} = 1; + } + my $start_page = + &Apache::loncommon::start_page('User Management',$js,$args); my $forminfo =<<"ENDFORMINFO"; -
- - - - - - + + + + + + + ENDFORMINFO - my $uhome=&Apache::lonnet::homeserver($ccuname,$ccdomain); - my %incdomains; - my %inccourses; - foreach my $item (values(%Apache::lonnet::hostdom)) { - $incdomains{$item}=1; - } - foreach my $key (keys(%env)) { - if ($key=~/^user\.priv\.cm\.\/(\w+)\/(\w+)/) { - $inccourses{$1.'_'.$2}=1; + my (%inccourses,$roledom); + if ($context eq 'course') { + $inccourses{$env{'request.course.id'}}=1; + $roledom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + } elsif ($context eq 'author') { + $roledom = $env{'request.role.domain'}; + } elsif ($context eq 'domain') { + foreach my $key (keys(%env)) { + $roledom = $env{'request.role.domain'}; + if ($key=~/^user\.priv\.cm\.\/($roledom)\/($match_username)/) { + $inccourses{$1.'_'.$2}=1; + } + } + } else { + foreach my $key (keys(%env)) { + if ($key=~/^user\.priv\.cm\.\/($match_domain)\/($match_username)/) { + $inccourses{$1.'_'.$2}=1; + } } } - if ($uhome eq 'no_host') { - my $home_server_list= - ''."\n". - &Apache::loncommon::home_server_option_list($ccdomain); - - my %lt=&Apache::lonlocal::texthash( - 'cnu' => "Create New User", - 'nu' => "New User", - 'id' => "in domain", - 'pd' => "Personal Data", - 'fn' => "First Name", - 'mn' => "Middle Name", - 'ln' => "Last Name", - 'gen' => "Generation", - 'idsn' => "ID/Student Number", - 'hs' => "Home Server", - 'lg' => "Login Data" - ); + if ($newuser) { my $portfolioform; - if (&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) { - # Current user has quota modification privileges - $portfolioform = &portfolio_quota($ccuname,$ccdomain); + 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 + $portfolioform = '
'.&portfolio_quota($ccuname,$ccdomain); } - my $genhelp=&Apache::loncommon::help_open_topic('Generation'); - &initialize_authen_forms(); - $r->print(< 'Create New User', + 'ast' => 'as a student', + 'ame' => 'as a member', + 'ind' => 'in domain', + 'lg' => 'Login Data', + 'hs' => "Home Server", + ); + $r->print(<$lt{'cnu'} +$response $forminfo -

$lt{'nu'} "$ccuname" $lt{'id'} $ccdomain

-

$lt{'pd'}

-

- - - - - - - - - -
$lt{'fn'}
$lt{'mn'}
$lt{'ln'}
$lt{'gen'}$genhelp
-$lt{'idsn'}

-$lt{'hs'}: -
-

$lt{'lg'}

-

$generalrule

-

$authformkrb

-

$authformint

-

$authformfsys

-

$authformloc

-
-$portfolioform -ENDNEWUSER +

$lt{'cnu'} "$ccuname" $lt{'ind'} $ccdomain +ENDTITLE + if ($env{'form.action'} eq 'singlestudent') { + if ($crstype eq 'Community') { + $r->print(' ('.$lt{'ame'}.')'); + } else { + $r->print(' ('.$lt{'ast'}.')'); + } + } + $r->print('

'."\n".'
'); + my $personal_table = + &personal_data_display($ccuname,$ccdomain,$newuser,$context, + $inst_results{$ccuname.':'.$ccdomain}); + $r->print($personal_table); + my ($home_server_pick,$numlib) = + &Apache::loncommon::home_server_form_item($ccdomain,'hserver', + 'default','hide'); + if ($numlib > 1) { + $r->print(" +
+$lt{'hs'}: $home_server_pick +
"); + } else { + $r->print($home_server_pick); + } + if (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) { + $r->print('

'.&mt('User Can Request Creation of Courses/Communities in this Domain?').'

'. + &Apache::loncommon::start_data_table(). + &build_tools_display($ccuname,$ccdomain, + 'requestcourses'). + &Apache::loncommon::end_data_table()); + } + $r->print('
'."\n".'

'. + $lt{'lg'}.'

'); + my ($fixedauth,$varauth,$authmsg); + if (ref($rulematch{$ccuname.':'.$ccdomain}) eq 'HASH') { + my $matchedrule = $rulematch{$ccuname.':'.$ccdomain}{'username'}; + my ($rules,$ruleorder) = + &Apache::lonnet::inst_userrules($ccdomain,'username'); + if (ref($rules) eq 'HASH') { + if (ref($rules->{$matchedrule}) eq 'HASH') { + my $authtype = $rules->{$matchedrule}{'authtype'}; + if ($authtype !~ /^(krb4|krb5|int|fsys|loc)$/) { + $r->print(&Apache::lonuserutils::set_login($ccdomain,$authformkrb,$authformint,$authformloc)); + } else { + my $authparm = $rules->{$matchedrule}{'authparm'}; + $authmsg = $rules->{$matchedrule}{'authmsg'}; + if ($authtype =~ /^krb(4|5)$/) { + my $ver = $1; + if ($authparm ne '') { + $fixedauth = <<"KERB"; + + + +KERB + } + } else { + $fixedauth = +''."\n"; + if ($rules->{$matchedrule}{'authparmfixed'}) { + $fixedauth .= +''."\n"; + } else { + if ($authtype eq 'int') { + $varauth = '
'. +&mt('[_1] Internally authenticated (with initial password [_2])','','')."'; + } elsif ($authtype eq 'loc') { + $varauth = '
'. +&mt('[_1] Local Authentication with argument [_2]','','')."\n"; + } else { + $varauth = +''."\n"; + } + } + } + } + } else { + $r->print(&Apache::lonuserutils::set_login($ccdomain,$authformkrb,$authformint,$authformloc)); + } + } + if ($authmsg) { + $r->print(<print(&Apache::lonuserutils::set_login($ccdomain,$authformkrb,$authformint,$authformloc)); + } + $r->print($portfolioform); + if ($env{'form.action'} eq 'singlestudent') { + $r->print(&date_sections_select($context,$newuser,$formname, + $permission)); + } + $r->print('
'); } else { # user already exists my %lt=&Apache::lonlocal::texthash( - 'cup' => "Change User Privileges", - 'usr' => "User", + 'cup' => "Modify existing user: ", + 'ens' => "Enroll one student: ", + 'enm' => "Enroll one member: ", 'id' => "in domain", - 'fn' => "first name", - 'mn' => "middle name", - 'ln' => "last name", - 'gen' => "generation" ); $r->print(<$lt{'cup'} $forminfo -

$lt{'usr'} "$ccuname" $lt{'id'} "$ccdomain"

+

ENDCHANGEUSER - # Get the users information - my %userenv = &Apache::lonnet::get('environment', - ['firstname','middlename','lastname','generation', - 'portfolioquota'],$ccdomain,$ccuname); - my %rolesdump=&Apache::lonnet::dump('roles',$ccdomain,$ccuname); - $r->print(' -
'. - &Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_header_row(). -''.$lt{'fn'}.''.$lt{'mn'}.''.$lt{'ln'}.''.$lt{'gen'}.''. - &Apache::loncommon::end_data_table_header_row(). - &Apache::loncommon::start_data_table_row()); - foreach my $item ('firstname','middlename','lastname','generation') { - if (&Apache::lonnet::allowed('mau',$ccdomain)) { - $r->print(<<"END"); - -END - } else { - $r->print(''.$userenv{$item}.''); - } + if ($env{'form.action'} eq 'singlestudent') { + if ($crstype eq 'Community') { + $r->print($lt{'enm'}); + } else { + $r->print($lt{'ens'}); + } + } else { + $r->print($lt{'cup'}); + } + $r->print(' "'.$ccuname.'" '.$lt{'id'}.' "'.$ccdomain.'"

'. + "\n".'
'); + my ($personal_table,$showforceid) = + &personal_data_display($ccuname,$ccdomain,$newuser,$context, + $inst_results{$ccuname.':'.$ccdomain}); + $r->print($personal_table); + if ($showforceid) { + $r->print(&Apache::lonuserutils::forceid_change($context)); + } + if (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) { + $r->print('

'.&mt('User Can Request Creation of Courses/Communities in this Domain?').'

'. + &Apache::loncommon::start_data_table()); + if ($env{'request.role.domain'} eq $ccdomain) { + $r->print(&build_tools_display($ccuname,$ccdomain,'requestcourses')); + } else { + $r->print(&coursereq_externaluser($ccuname,$ccdomain, + $env{'request.role.domain'})); + } + $r->print(&Apache::loncommon::end_data_table()); + } + $r->print('
'); + my $user_auth_text = &user_authentication($ccuname,$ccdomain,$formname); + my ($user_quota_text,$user_tools_text,$user_reqcrs_text); + if ((&Apache::lonnet::allowed('mpq',$ccdomain)) || + (&Apache::lonnet::allowed('mut',$ccdomain))) { + # Current user has quota modification privileges + $user_quota_text = &portfolio_quota($ccuname,$ccdomain); + } + if (!&Apache::lonnet::allowed('mpq',$ccdomain)) { + if (&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) { + # Get the user's portfolio information + my %portq = &Apache::lonnet::get('environment',['portfolioquota'], + $ccdomain,$ccuname); + my %lt=&Apache::lonlocal::texthash( + 'dska' => "Disk space allocated to user's portfolio files", + 'youd' => "You do not have privileges to modify the portfolio quota for this user.", + 'ichr' => "If a change is required, contact a domain coordinator for the domain", + ); + $user_quota_text = <$lt{'dska'} +$lt{'youd'} $lt{'ichr'}: $ccdomain +ENDNOPORTPRIV + } + } + if (!&Apache::lonnet::allowed('mut',$ccdomain)) { + if (&Apache::lonnet::allowed('mut',$env{'request.role.domain'})) { + my %lt=&Apache::lonlocal::texthash( + 'utav' => "User Tools Availability", + 'yodo' => "You do not have privileges to modify Portfolio, Blog or Personal Information Page settings for this user.", + 'ifch' => "If a change is required, contact a domain coordinator for the domain", + ); + $user_tools_text = <$lt{'utav'} +$lt{'yodo'} $lt{'ifch'}: $ccdomain +ENDNOTOOLSPRIV + } + } + if ($user_auth_text ne '') { + $r->print('
'.$user_auth_text); + if ($user_quota_text ne '') { + $r->print($user_quota_text); + } + if ($user_tools_text ne '') { + $r->print($user_tools_text); + } + if ($env{'form.action'} eq 'singlestudent') { + $r->print(&date_sections_select($context,$newuser,$formname)); + } + } elsif ($user_quota_text ne '') { + $r->print('
'.$user_quota_text); + if ($user_tools_text ne '') { + $r->print($user_tools_text); + } + if ($env{'form.action'} eq 'singlestudent') { + $r->print(&date_sections_select($context,$newuser,$formname)); + } + } elsif ($user_tools_text ne '') { + $r->print('
'.$user_tools_text); + if ($env{'form.action'} eq 'singlestudent') { + $r->print(&date_sections_select($context,$newuser,$formname)); + } + } else { + if ($env{'form.action'} eq 'singlestudent') { + $r->print('
'. + &date_sections_select($context,$newuser,$formname)); + } + } + $r->print('
'); + if ($env{'form.action'} ne 'singlestudent') { + &display_existing_roles($r,$ccuname,$ccdomain,\%inccourses,$context, + $roledom,$crstype); + } + } ## End of new user/old user logic + if ($env{'form.action'} eq 'singlestudent') { + my $btntxt; + if ($crstype eq 'Community') { + $btntxt = &mt('Enroll Member'); + } else { + $btntxt = &mt('Enroll Student'); } - $r->print(&Apache::loncommon::end_data_table_row(). - &Apache::loncommon::end_data_table()); - # Build up table of user roles to allow revocation of a role. - my ($tmp) = keys(%rolesdump); - unless ($tmp =~ /^(con_lost|error)/i) { - my $now=time; - my %lt=&Apache::lonlocal::texthash( - 'rer' => "Revoke Existing Roles", - 'rev' => "Revoke", + $r->print('
'."\n"); + } else { + $r->print('

'.&mt('Add Roles').'

'); + my $addrolesdisplay = 0; + if ($context eq 'domain' || $context eq 'author') { + $addrolesdisplay = &new_coauthor_roles($r,$ccuname,$ccdomain); + } + if ($context eq 'domain') { + my $add_domainroles = &new_domain_roles($r); + if (!$addrolesdisplay) { + $addrolesdisplay = $add_domainroles; + } + $r->print(&course_level_dc($env{'request.role.domain'},'Course')); + $r->print('
'."\n"); + } elsif ($context eq 'author') { + if ($addrolesdisplay) { + $r->print('
print(' onclick="auth_check()" \>'."\n"); + } else { + $r->print('onclick="this.form.submit()" \>'."\n"); + } + } else { + $r->print('
'. + &mt('Back to previous page').''); + } + } else { + $r->print(&course_level_table(%inccourses)); + $r->print('
'."\n"); + } + } + $r->print(&Apache::lonhtmlcommon::echo_form_input(['phase','userrole','ccdomain','prevphase','currstate','ccuname','ccdomain'])); + $r->print(''); + $r->print(''); + return; +} + +sub singleuser_breadcrumb { + my ($crstype) = @_; + my %breadcrumb_text; + if ($env{'form.action'} eq 'singlestudent') { + if ($crstype eq 'Community') { + $breadcrumb_text{'search'} = 'Enroll a member'; + } else { + $breadcrumb_text{'search'} = 'Enroll a student'; + } + $breadcrumb_text{'userpicked'} = 'Select a user', + $breadcrumb_text{'modify'} = 'Set section/dates', + } else { + $breadcrumb_text{'search'} = 'Create/modify a user'; + $breadcrumb_text{'userpicked'} = 'Select a user', + $breadcrumb_text{'modify'} = 'Set user role', + } + return %breadcrumb_text; +} + +sub date_sections_select { + my ($context,$newuser,$formname,$permission) = @_; + my $cid = $env{'request.course.id'}; + my ($cnum,$cdom) = &Apache::lonuserutils::get_course_identity($cid); + my $date_table = '

'.&mt('Starting and Ending Dates').'

'."\n". + &Apache::lonuserutils::date_setting_table(undef,undef,$context, + undef,$formname,$permission); + my $rowtitle = 'Section'; + my $secbox = '

'.&mt('Section').'

'."\n". + &Apache::lonuserutils::section_picker($cdom,$cnum,'st',$rowtitle, + $permission); + my $output = $date_table.$secbox; + return $output; +} + +sub validation_javascript { + my ($context,$ccdomain,$pjump_def,$groupslist,$newuser,$formname, + $loaditem) = @_; + my $dc_setcourse_code = ''; + my $nondc_setsection_code = ''; + if ($context eq 'domain') { + my $dcdom = $env{'request.role.domain'}; + $loaditem->{'onload'} = "document.cu.coursedesc.value='';"; + $dc_setcourse_code = + &Apache::lonuserutils::dc_setcourse_js('cu','singleuser',$context); + } else { + my $checkauth; + if (($newuser) || (&Apache::lonnet::allowed('mau',$ccdomain))) { + $checkauth = 1; + } + if ($context eq 'course') { + $nondc_setsection_code = + &Apache::lonuserutils::setsections_javascript($formname,$groupslist, + undef,$checkauth); + } + if ($checkauth) { + $nondc_setsection_code .= + &Apache::lonuserutils::verify_authen($formname,$context); + } + } + my $js = &user_modification_js($pjump_def,$dc_setcourse_code, + $nondc_setsection_code,$groupslist); + my ($jsback,$elements) = &crumb_utilities(); + $js .= "\n". + ''."\n"; + return $js; +} + +sub display_existing_roles { + my ($r,$ccuname,$ccdomain,$inccourses,$context,$roledom,$crstype) = @_; + my $now=time; + my %lt=&Apache::lonlocal::texthash( + 'rer' => "Existing Roles", + 'rev' => "Revoke", 'del' => "Delete", - 'ren' => "Re-Enable", + 'ren' => "Re-Enable", 'rol' => "Role", 'ext' => "Extent", 'sta' => "Start", - 'end' => "End" - ); - my (%roletext,%sortrole,%roleclass,%rolepriv); - foreach my $area (sort { my $a1=join('_',(split('_',$a))[1,0]); - my $b1=join('_',(split('_',$b))[1,0]); - return $a1 cmp $b1; - } keys(%rolesdump)) { - next if ($area =~ /^rolesdef/); - my $envkey=$area; - my $role = $rolesdump{$area}; - my $thisrole=$area; - $area =~ s/\_\w\w$//; - my ($role_code,$role_end_time,$role_start_time) = - split(/_/,$role); + 'end' => "End", + ); + my (%rolesdump,%roletext,%sortrole,%roleclass,%rolepriv); + if ($context eq 'course' || $context eq 'author') { + my @roles = &Apache::lonuserutils::roles_by_context($context,1,$crstype); + my %roleshash = + &Apache::lonnet::get_my_roles($ccuname,$ccdomain,'userroles', + ['active','previous','future'],\@roles,$roledom,1); + foreach my $key (keys(%roleshash)) { + my ($start,$end) = split(':',$roleshash{$key}); + next if ($start eq '-1' || $end eq '-1'); + my ($rnum,$rdom,$role,$sec) = split(':',$key); + if ($context eq 'course') { + next unless (($rnum eq $env{'course.'.$env{'request.course.id'}.'.num'}) + && ($rdom eq $env{'course.'.$env{'request.course.id'}.'.domain'})); + } elsif ($context eq 'author') { + next unless (($rnum eq $env{'user.name'}) && ($rdom eq $env{'request.role.domain'})); + } + my ($newkey,$newvalue,$newrole); + $newkey = '/'.$rdom.'/'.$rnum; + if ($sec ne '') { + $newkey .= '/'.$sec; + } + $newvalue = $role; + if ($role =~ /^cr/) { + $newrole = 'cr'; + } else { + $newrole = $role; + } + $newkey .= '_'.$newrole; + if ($start ne '' && $end ne '') { + $newvalue .= '_'.$end.'_'.$start; + } elsif ($end ne '') { + $newvalue .= '_'.$end; + } + $rolesdump{$newkey} = $newvalue; + } + } else { + my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1}); + %rolesdump=&Apache::lonnet::dump('roles',$ccdomain,$ccuname,'.',undef,$extra); + } + # Build up table of user roles to allow revocation and re-enabling of roles. + my ($tmp) = keys(%rolesdump); + return if ($tmp =~ /^(con_lost|error)/i); + foreach my $area (sort { my $a1=join('_',(split('_',$a))[1,0]); + my $b1=join('_',(split('_',$b))[1,0]); + return $a1 cmp $b1; + } keys(%rolesdump)) { + next if ($area =~ /^rolesdef/); + my $envkey=$area; + my $role = $rolesdump{$area}; + my $thisrole=$area; + $area =~ s/\_\w\w$//; + my ($role_code,$role_end_time,$role_start_time) = + split(/_/,$role); # Is this a custom role? Get role owner and title. - my ($croleudom,$croleuname,$croletitle)= - ($role_code=~/^cr\/(\w+)\/(\w+)\/(\w+)$/); - my $allowed=0; - my $delallowed=0; - my $sortkey=$role_code; - my $class='Unknown'; - if ($area =~ /^\/(\w+)\/(\d\w+)/ ) { - $class='Course'; - my ($coursedom,$coursedir) = ($1,$2); - $sortkey.="\0$coursedom"; - # $1.'_'.$2 is the course id (eg. 103_12345abcef103l3). - my %coursedata= - &Apache::lonnet::coursedescription($1.'_'.$2); - my $carea; - if (defined($coursedata{'description'})) { - $carea=$coursedata{'description'}. - '
'.&mt('Domain').': '.$coursedom.(' 'x8). - &Apache::loncommon::syllabuswrapper('Syllabus',$coursedir,$coursedom); - $sortkey.="\0".$coursedata{'description'}; - $class=$coursedata{'type'}; - } else { - $carea=&mt('Unavailable course').': '.$area; - $sortkey.="\0".&mt('Unavailable course').': '.$area; - } - $sortkey.="\0$coursedir"; - $inccourses{$1.'_'.$2}=1; - if ((&Apache::lonnet::allowed('c'.$role_code,$1.'/'.$2)) || - (&Apache::lonnet::allowed('c'.$role_code,$ccdomain))) { - $allowed=1; - } - if ((&Apache::lonnet::allowed('dro',$1)) || - (&Apache::lonnet::allowed('dro',$ccdomain))) { - $delallowed=1; - } + my ($croleudom,$croleuname,$croletitle)= + ($role_code=~m{^cr/($match_domain)/($match_username)/(\w+)$}); + my $allowed=0; + my $delallowed=0; + my $sortkey=$role_code; + my $class='Unknown'; + if ($area =~ m{^/($match_domain)/($match_courseid)} ) { + $class='Course'; + my ($coursedom,$coursedir) = ($1,$2); + my $cid = $1.'_'.$2; + # $1.'_'.$2 is the course id (eg. 103_12345abcef103l3). + my %coursedata= + &Apache::lonnet::coursedescription($cid); + if ($coursedir =~ /^$match_community$/) { + $class='Community'; + } + $sortkey.="\0$coursedom"; + my $carea; + if (defined($coursedata{'description'})) { + $carea=$coursedata{'description'}. + '
'.&mt('Domain').': '.$coursedom.(' 'x8). + &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$coursedir,$coursedom); + $sortkey.="\0".$coursedata{'description'}; + } else { + if ($class eq 'Community') { + $carea=&mt('Unavailable community').': '.$area; + $sortkey.="\0".&mt('Unavailable community').': '.$area; + } else { + $carea=&mt('Unavailable course').': '.$area; + $sortkey.="\0".&mt('Unavailable course').': '.$area; + } + } + $sortkey.="\0$coursedir"; + $inccourses->{$cid}=1; + if ((&Apache::lonnet::allowed('c'.$role_code,$coursedom.'/'.$coursedir)) || + (&Apache::lonnet::allowed('c'.$role_code,$ccdomain))) { + $allowed=1; + } + unless ($allowed) { + my $isowner = &is_courseowner($cid,$coursedata{'internal.courseowner'}); + if ($isowner) { + if (($role_code eq 'co') && ($class eq 'Community')) { + $allowed = 1; + } elsif (($role_code eq 'cc') && ($class eq 'Course')) { + $allowed = 1; + } + } + } + if ((&Apache::lonnet::allowed('dro',$coursedom)) || + (&Apache::lonnet::allowed('dro',$ccdomain))) { + $delallowed=1; + } # - custom role. Needs more info, too - if ($croletitle) { - if (&Apache::lonnet::allowed('ccr',$1.'/'.$2)) { - $allowed=1; - $thisrole.='.'.$role_code; - } - } - # Compute the background color based on $area - if ($area=~/^\/(\w+)\/(\d\w+)\/(\w+)/) { - $carea.='
Section: '.$3; - $sortkey.="\0$3"; - } - $area=$carea; - } else { - $sortkey.="\0".$area; - # Determine if current user is able to revoke privileges - if ($area=~ /^\/(\w+)\//) { - if ((&Apache::lonnet::allowed('c'.$role_code,$1)) || - (&Apache::lonnet::allowed('c'.$role_code,$ccdomain))) { - $allowed=1; - } - if (((&Apache::lonnet::allowed('dro',$1)) || - (&Apache::lonnet::allowed('dro',$ccdomain))) && - ($role_code ne 'dc')) { - $delallowed=1; - } - } else { - if (&Apache::lonnet::allowed('c'.$role_code,'/')) { - $allowed=1; - } - } - if ($role_code eq 'ca' || $role_code eq 'au') { - $class='Construction Space'; - } elsif ($role_code eq 'su') { - $class='System'; - } else { - $class='Domain'; - } - } - if (($role_code eq 'ca') || ($role_code eq 'aa')) { - $area=~/\/(\w+)\/(\w+)/; - if (&authorpriv($2,$1)) { - $allowed=1; - } else { - $allowed=0; - } - } - my $row = ''; - $row.= ''; - my $active=1; - $active=0 if (($role_end_time) && ($now>$role_end_time)); - if (($active) && ($allowed)) { - $row.= ''; - } else { - if ($active) { - $row.=' '; - } else { - $row.=&mt('expired or revoked'); - } - } - $row.=''; - if ($allowed && !$active) { - $row.= ''; - } else { - $row.=' '; - } - $row.=''; - if ($delallowed) { - $row.= ''; - } else { - $row.=' '; - } - my $plaintext=''; - unless ($croletitle) { - $plaintext=&Apache::lonnet::plaintext($role_code,$class) - } else { - $plaintext= - "Customrole '$croletitle' defined by $croleuname\@$croleudom"; - } - $row.= ''.$plaintext. - ''.$area. - ''.($role_start_time?localtime($role_start_time) - : ' ' ). - ''.($role_end_time ?localtime($role_end_time) - : ' ' ) - .""; - $sortrole{$sortkey}=$envkey; - $roletext{$envkey}=$row; - $roleclass{$envkey}=$class; - $rolepriv{$envkey}=$allowed; - #$r->print($row); - } # end of foreach (table building loop) - my $rolesdisplay = 0; - my %output = (); - foreach my $type ('Construction Space','Course','Group','Domain','System','Unknown') { - $output{$type} = ''; - foreach my $which (sort {uc($a) cmp uc($b)} (keys(%sortrole))) { - if ( ($roleclass{$sortrole{$which}} =~ /^\Q$type\E/ ) && ($rolepriv{$sortrole{$which}}) ) { - $output{$type}.= - &Apache::loncommon::start_data_table_row(). - $roletext{$sortrole{$which}}. - &Apache::loncommon::end_data_table_row(); - } - } - unless($output{$type} eq '') { - $output{$type} = ''. - "".&mt($type)."". - $output{$type}; - $rolesdisplay = 1; - } - } - if ($rolesdisplay == 1) { - $r->print(' -
+ if ($croletitle) { + if (&Apache::lonnet::allowed('ccr',$coursedom.'/'.$coursedir)) { + $allowed=1; + $thisrole.='.'.$role_code; + } + } + if ($area=~m{^/($match_domain)/($match_courseid)/(\w+)}) { + $carea.='
Section: '.$3; + $sortkey.="\0$3"; + if (!$allowed) { + if ($env{'request.course.sec'} eq $3) { + if (&Apache::lonnet::allowed('c'.$role_code,$1.'/'.$2.'/'.$3)) { + $allowed = 1; + } + } + } + } + $area=$carea; + } else { + $sortkey.="\0".$area; + # Determine if current user is able to revoke privileges + if ($area=~m{^/($match_domain)/}) { + if ((&Apache::lonnet::allowed('c'.$role_code,$1)) || + (&Apache::lonnet::allowed('c'.$role_code,$ccdomain))) { + $allowed=1; + } + if (((&Apache::lonnet::allowed('dro',$1)) || + (&Apache::lonnet::allowed('dro',$ccdomain))) && + ($role_code ne 'dc')) { + $delallowed=1; + } + } else { + if (&Apache::lonnet::allowed('c'.$role_code,'/')) { + $allowed=1; + } + } + if ($role_code eq 'ca' || $role_code eq 'au') { + $class='Construction Space'; + } elsif ($role_code eq 'su') { + $class='System'; + } else { + $class='Domain'; + } + } + if (($role_code eq 'ca') || ($role_code eq 'aa')) { + $area=~m{/($match_domain)/($match_username)}; + if (&Apache::lonuserutils::authorpriv($2,$1)) { + $allowed=1; + } else { + $allowed=0; + } + } + my $row = ''; + $row.= ''; + my $active=1; + $active=0 if (($role_end_time) && ($now>$role_end_time)); + if (($active) && ($allowed)) { + $row.= ''; + } else { + if ($active) { + $row.=' '; + } else { + $row.=&mt('expired or revoked'); + } + } + $row.=''; + if ($allowed && !$active) { + $row.= ''; + } else { + $row.=' '; + } + $row.=''; + if ($delallowed) { + $row.= ''; + } else { + $row.=' '; + } + my $plaintext=''; + if (!$croletitle) { + $plaintext=&Apache::lonnet::plaintext($role_code,$class) + } else { + $plaintext= + &mt('Customrole [_1][_2]defined by [_3]', + '"'.$croletitle.'"', + '
', + $croleuname.':'.$croleudom); + } + $row.= ''.$plaintext. + ''.$area. + ''.($role_start_time?&Apache::lonlocal::locallocaltime($role_start_time) + : ' ' ). + ''.($role_end_time ?&Apache::lonlocal::locallocaltime($role_end_time) + : ' ' ) + .""; + $sortrole{$sortkey}=$envkey; + $roletext{$envkey}=$row; + $roleclass{$envkey}=$class; + $rolepriv{$envkey}=$allowed; + } # end of foreach (table building loop) + + my $rolesdisplay = 0; + my %output = (); + foreach my $type ('Construction Space','Course','Community','Domain','System','Unknown') { + $output{$type} = ''; + foreach my $which (sort {uc($a) cmp uc($b)} (keys(%sortrole))) { + if ( ($roleclass{$sortrole{$which}} =~ /^\Q$type\E/ ) && ($rolepriv{$sortrole{$which}}) ) { + $output{$type}.= + &Apache::loncommon::start_data_table_row(). + $roletext{$sortrole{$which}}. + &Apache::loncommon::end_data_table_row(); + } + } + unless($output{$type} eq '') { + $output{$type} = ''. + "".&mt($type)."". + $output{$type}; + $rolesdisplay = 1; + } + } + if ($rolesdisplay == 1) { + my $contextrole=''; + if ($env{'request.course.id'}) { + if (&Apache::loncommon::course_type() eq 'Community') { + $contextrole = &mt('Existing Roles in this Community'); + } else { + $contextrole = &mt('Existing Roles in this Course'); + } + } elsif ($env{'request.role'} =~ /^au\./) { + $contextrole = &mt('Existing Co-Author Roles in your Construction Space'); + } else { + $contextrole = &mt('Existing Roles in this Domain'); + } + $r->print('

'.$lt{'rer'}.'

'. +'
'.$contextrole.'
'. &Apache::loncommon::start_data_table("LC_createuser"). &Apache::loncommon::start_data_table_header_row(). ''.$lt{'rev'}.''.$lt{'ren'}.''.$lt{'del'}. ''.$lt{'rol'}.''.$lt{'ext'}. ''.$lt{'sta'}.''.$lt{'end'}.''. &Apache::loncommon::end_data_table_header_row()); - foreach my $type ('Construction Space','Course','Group','Domain','System','Unknown') { - if ($output{$type}) { - $r->print($output{$type}."\n"); - } - } - $r->print(&Apache::loncommon::end_data_table()); - } - } # End of unless - my $currentauth=&Apache::lonnet::queryauthenticate($ccuname,$ccdomain); - if ($currentauth=~/^krb(4|5):/) { - $currentauth=~/^krb(4|5):(.*)/; - my $krbdefdom=$2; - my %param = ( formname => 'document.cu', - kerb_def_dom => $krbdefdom - ); - $loginscript = &Apache::loncommon::authform_header(%param); - } - # Check for a bad authentication type - unless ($currentauth=~/^krb(4|5):/ or - $currentauth=~/^unix:/ or - $currentauth=~/^internal:/ or - $currentauth=~/^localauth:/ - ) { # bad authentication scheme - if (&Apache::lonnet::allowed('mau',$ccdomain)) { - &initialize_authen_forms(); - my %lt=&Apache::lonlocal::texthash( - 'err' => "ERROR", - 'uuas' => "This user has an unrecognized authentication scheme", - 'sldb' => "Please specify login data below", - 'ld' => "Login Data" - ); - $r->print(< - -$lt{'err'}: -$lt{'uuas'} ($currentauth). $lt{'sldb'}. -

$lt{'ld'}

-

$generalrule

-

$authformkrb

-

$authformint

-

$authformfsys

-

$authformloc

-ENDBADAUTH - } else { - # This user is not allowed to modify the user's - # authentication scheme, so just notify them of the problem - my %lt=&Apache::lonlocal::texthash( - 'err' => "ERROR", - 'uuas' => "This user has an unrecognized authentication scheme", - 'adcs' => "Please alert a domain coordinator of this situation" - ); - $r->print(< - $lt{'err'}: -$lt{'uuas'} ($currentauth). $lt{'adcs'}. -
-ENDBADAUTH - } - } else { # Authentication type is valid - my $authformcurrent=''; - my $authform_other=''; - &initialize_authen_forms(); - if ($currentauth=~/^krb(4|5):/) { - $authformcurrent=$authformkrb; - $authform_other="

$authformint

\n". - "

$authformfsys

$authformloc

"; - } - elsif ($currentauth=~/^internal:/) { - $authformcurrent=$authformint; - $authform_other="

$authformkrb

". - "

$authformfsys

$authformloc

"; - } - elsif ($currentauth=~/^unix:/) { - $authformcurrent=$authformfsys; - $authform_other="

$authformkrb

". - "

$authformint

$authformloc;

"; - } - elsif ($currentauth=~/^localauth:/) { - $authformcurrent=$authformloc; - $authform_other="

$authformkrb

". - "

$authformint

$authformfsys

"; - } - $authformcurrent.=' (will override current values)
'; - if (&Apache::lonnet::allowed('mau',$ccdomain)) { - # Current user has login modification privileges - my %lt=&Apache::lonlocal::texthash( - 'ccld' => "Change Current Login Data", - 'enld' => "Enter New Login Data" - ); - $r->print(< - -

$lt{'ccld'}

-

$generalrule

-

$authformnop

-

$authformcurrent

-

$lt{'enld'}

-$authform_other -ENDOTHERAUTHS - } else { - if (&Apache::lonnet::allowed('mau',$env{'request.role.domain'})) { - my %lt=&Apache::lonlocal::texthash( - 'ccld' => "Change Current Login Data", - 'yodo' => "You do not have privileges to modify the authentication configuration for this user.", - 'ifch' => "If a change is required, contact a domain coordinator for the domain", - ); - $r->print(< -

$lt{'ccld'}

-$lt{'yodo'} $lt{'ifch'}: $ccdomain -ENDNOPRIV - } - } - if (&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) { - # Current user has quota modification privileges - $r->print(&portfolio_quota($ccuname,$ccdomain)); + foreach my $type ('Construction Space','Course','Community','Domain','System','Unknown') { + if ($output{$type}) { + $r->print($output{$type}."\n"); } - } ## End of "check for bad authentication type" logic - } ## End of new user/old user logic - $r->print('

'.&mt('Add Roles').'

'); -# -# Co-Author -# - if (&authorpriv($env{'user.name'},$env{'request.role.domain'}) && + } + $r->print(&Apache::loncommon::end_data_table()); + } + return; +} + +sub new_coauthor_roles { + my ($r,$ccuname,$ccdomain) = @_; + my $addrolesdisplay = 0; + # + # Co-Author + # + if (&Apache::lonuserutils::authorpriv($env{'user.name'}, + $env{'request.role.domain'}) && ($env{'user.name'} ne $ccuname || $env{'user.domain'} ne $ccdomain)) { # No sense in assigning co-author role to yourself - my $cuname=$env{'user.name'}; + $addrolesdisplay = 1; + my $cuname=$env{'user.name'}; my $cudom=$env{'request.role.domain'}; - my %lt=&Apache::lonlocal::texthash( - 'cs' => "Construction Space", - 'act' => "Activate", + my %lt=&Apache::lonlocal::texthash( + 'cs' => "Construction Space", + 'act' => "Activate", 'rol' => "Role", 'ext' => "Extent", 'sta' => "Start", @@ -919,45 +1716,61 @@ ENDNOPRIV 'caa' => "Assistant Co-Author", 'ssd' => "Set Start Date", 'sed' => "Set End Date" - ); - $r->print('

'.$lt{'cs'}.'

'."\n". - &Apache::loncommon::start_data_table()."\n". - &Apache::loncommon::start_data_table_header_row()."\n". - ''.$lt{'act'}.''.$lt{'rol'}.''. - ''.$lt{'ext'}.''.$lt{'sta'}.''. - ''.$lt{'end'}.''."\n". - &Apache::loncommon::end_data_table_header_row()."\n". - &Apache::loncommon::start_data_table_row()."\n". - ' - + ); + $r->print('

'.$lt{'cs'}.'

'."\n". + &Apache::loncommon::start_data_table()."\n". + &Apache::loncommon::start_data_table_header_row()."\n". + ''.$lt{'act'}.''.$lt{'rol'}.''. + ''.$lt{'ext'}.''.$lt{'sta'}.''. + ''.$lt{'end'}.''."\n". + &Apache::loncommon::end_data_table_header_row()."\n". + &Apache::loncommon::start_data_table_row().' + + '.$lt{'cau'}.' '.$cudom.'_'.$cuname.' '.$lt{'ssd'}.' - + '.$lt{'sed'}.''."\n". - &Apache::loncommon::end_data_table_row()."\n". - &Apache::loncommon::start_data_table_row()."\n". -' + &Apache::loncommon::end_data_table_row()."\n". + &Apache::loncommon::start_data_table_row()."\n". +' '.$lt{'caa'}.' '.$cudom.'_'.$cuname.' - + '.$lt{'ssd'}.' - + '.$lt{'sed'}.''."\n". - &Apache::loncommon::end_data_table_row()."\n". - &Apache::loncommon::end_data_table()); + &Apache::loncommon::end_data_table_row()."\n". + &Apache::loncommon::end_data_table()); + } elsif ($env{'request.role'} =~ /^au\./) { + if (!(&Apache::lonuserutils::authorpriv($env{'user.name'}, + $env{'request.role.domain'}))) { + $r->print(''. + &mt('You do not have privileges to assign co-author roles.'). + ''); + } elsif (($env{'user.name'} eq $ccuname) && + ($env{'user.domain'} eq $ccdomain)) { + $r->print(&mt('Assigning yourself a co-author or assistant co-author role in your own author area in Construction Space is not permitted')); + } } -# -# Domain level -# + return $addrolesdisplay;; +} + +sub new_domain_roles { + my ($r) = @_; + my $addrolesdisplay = 0; + # + # Domain level + # my $num_domain_level = 0; - my $domaintext = + my $domaintext = '

'.&mt('Domain Level').'

'. &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). @@ -965,86 +1778,502 @@ ENDNOPRIV &mt('Extent').''. ''.&mt('Start').''.&mt('End').''. &Apache::loncommon::end_data_table_header_row(); - foreach my $thisdomain ( sort( keys(%incdomains))) { - foreach my $role ('dc','li','dg','au','sc') { + my @allroles = &Apache::lonuserutils::roles_by_context('domain'); + foreach my $thisdomain (sort(&Apache::lonnet::all_domains())) { + foreach my $role (@allroles) { + next if ($role eq 'ad'); if (&Apache::lonnet::allowed('c'.$role,$thisdomain)) { my $plrole=&Apache::lonnet::plaintext($role); - my %lt=&Apache::lonlocal::texthash( + my %lt=&Apache::lonlocal::texthash( 'ssd' => "Set Start Date", 'sed' => "Set End Date" - ); + ); $num_domain_level ++; - $domaintext .= + $domaintext .= &Apache::loncommon::start_data_table_row(). -' +' '.$plrole.' '.$thisdomain.' - + '.$lt{'ssd'}.' - + '.$lt{'sed'}.''. &Apache::loncommon::end_data_table_row(); } - } + } } $domaintext.= &Apache::loncommon::end_data_table(); if ($num_domain_level > 0) { $r->print($domaintext); + $addrolesdisplay = 1; } -# -# Course and group levels -# + return $addrolesdisplay; +} + +sub user_authentication { + my ($ccuname,$ccdomain,$formname) = @_; + my $currentauth=&Apache::lonnet::queryauthenticate($ccuname,$ccdomain); + my $outcome; + # Check for a bad authentication type + if ($currentauth !~ /^(krb4|krb5|unix|internal|localauth):/) { + # bad authentication scheme + my %lt=&Apache::lonlocal::texthash( + 'err' => "ERROR", + 'uuas' => "This user has an unrecognized authentication scheme", + 'adcs' => "Please alert a domain coordinator of this situation", + 'sldb' => "Please specify login data below", + 'ld' => "Login Data" + ); + if (&Apache::lonnet::allowed('mau',$ccdomain)) { + &initialize_authen_forms($ccdomain,$formname); + + my $choices = &Apache::lonuserutils::set_login($ccdomain,$authformkrb,$authformint,$authformloc); + $outcome = < +// + +$lt{'err'}: +$lt{'uuas'} ($currentauth). $lt{'sldb'}. +

$lt{'ld'}

+$choices +ENDBADAUTH + } else { + # This user is not allowed to modify the user's + # authentication scheme, so just notify them of the problem + $outcome = < $lt{'err'}: +$lt{'uuas'} ($currentauth). $lt{'adcs'}. + +ENDBADAUTH + } + } else { # Authentication type is valid + &initialize_authen_forms($ccdomain,$formname,$currentauth,'modifyuser'); + my ($authformcurrent,$can_modify,@authform_others) = + &modify_login_block($ccdomain,$currentauth); + if (&Apache::lonnet::allowed('mau',$ccdomain)) { + # Current user has login modification privileges + my %lt=&Apache::lonlocal::texthash ( + 'ld' => "Login Data", + 'ccld' => "Change Current Login Data", + 'enld' => "Enter New Login Data" + ); + $outcome = + ''."\n". + '

'.$lt{'ld'}.'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(). + ''.$authformnop; + if ($can_modify) { + $outcome .= ''."\n". + &Apache::loncommon::end_data_table_row(). + &Apache::loncommon::start_data_table_row(). + ''.$authformcurrent.''. + &Apache::loncommon::end_data_table_row()."\n"; + } else { + $outcome .= ' ('.$authformcurrent.')'. + &Apache::loncommon::end_data_table_row()."\n"; + } + foreach my $item (@authform_others) { + $outcome .= &Apache::loncommon::start_data_table_row(). + ''.$item.''. + &Apache::loncommon::end_data_table_row()."\n"; + } + $outcome .= &Apache::loncommon::end_data_table(); + } else { + if (&Apache::lonnet::allowed('mau',$env{'request.role.domain'})) { + my %lt=&Apache::lonlocal::texthash( + 'ccld' => "Change Current Login Data", + 'yodo' => "You do not have privileges to modify the authentication configuration for this user.", + 'ifch' => "If a change is required, contact a domain coordinator for the domain", + ); + $outcome .= <$lt{'ccld'} +$lt{'yodo'} $lt{'ifch'}: $ccdomain + +ENDNOPRIV + } + } + } ## End of "check for bad authentication type" logic + return $outcome; +} + +sub modify_login_block { + my ($dom,$currentauth) = @_; + my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom); + my ($authnum,%can_assign) = + &Apache::loncommon::get_assignable_auth($dom); + my ($authformcurrent,@authform_others,$show_override_msg); + if ($currentauth=~/^krb(4|5):/) { + $authformcurrent=$authformkrb; + if ($can_assign{'int'}) { + push(@authform_others,$authformint); + } + if ($can_assign{'loc'}) { + push(@authform_others,$authformloc); + } + if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) { + $show_override_msg = 1; + } + } elsif ($currentauth=~/^internal:/) { + $authformcurrent=$authformint; + if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) { + push(@authform_others,$authformkrb); + } + if ($can_assign{'loc'}) { + push(@authform_others,$authformloc); + } + if ($can_assign{'int'}) { + $show_override_msg = 1; + } + } elsif ($currentauth=~/^unix:/) { + $authformcurrent=$authformfsys; + if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) { + push(@authform_others,$authformkrb); + } + if ($can_assign{'int'}) { + push(@authform_others,$authformint); + } + if ($can_assign{'loc'}) { + push(@authform_others,$authformloc); + } + if ($can_assign{'fsys'}) { + $show_override_msg = 1; + } + } elsif ($currentauth=~/^localauth:/) { + $authformcurrent=$authformloc; + if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) { + push(@authform_others,$authformkrb); + } + if ($can_assign{'int'}) { + push(@authform_others,$authformint); + } + if ($can_assign{'loc'}) { + $show_override_msg = 1; + } + } + if ($show_override_msg) { + $authformcurrent = ''."\n". + ''. + ''. + '
'.$authformcurrent. + '
   '.&mt('Currently in use').''. + &mt('will override current values'). + '
'; + } + return ($authformcurrent,$show_override_msg,@authform_others); +} - if ($env{'request.role'} =~ m-^dc\./(\w+)/$-) { - $r->print(&course_level_dc($1,'Course')); - $r->print('
'."\n"); +sub personal_data_display { + my ($ccuname,$ccdomain,$newuser,$context,$inst_results,$rolesarray) = @_; + my ($output,$showforceid,%userenv,%canmodify,%canmodify_status); + my @userinfo = ('firstname','middlename','lastname','generation', + 'permanentemail','id'); + my $rowcount = 0; + my $editable = 0; + %canmodify_status = + &Apache::lonuserutils::can_modify_userinfo($context,$ccdomain, + ['inststatus'],$rolesarray); + if (!$newuser) { + # Get the users information + %userenv = &Apache::lonnet::get('environment', + ['firstname','middlename','lastname','generation', + 'permanentemail','id','inststatus'],$ccdomain,$ccuname); + %canmodify = + &Apache::lonuserutils::can_modify_userinfo($context,$ccdomain, + \@userinfo,$rolesarray); + } elsif ($context eq 'selfcreate') { + %canmodify = &selfcreate_canmodify($context,$ccdomain,\@userinfo, + $inst_results,$rolesarray); + } + my %lt=&Apache::lonlocal::texthash( + 'pd' => "Personal Data", + 'firstname' => "First Name", + 'middlename' => "Middle Name", + 'lastname' => "Last Name", + 'generation' => "Generation", + 'permanentemail' => "Permanent e-mail address", + 'id' => "Student/Employee ID", + 'lg' => "Login Data", + 'inststatus' => "Affiliation", + ); + my %textboxsize = ( + firstname => '15', + middlename => '15', + lastname => '15', + generation => '5', + permanentemail => '25', + id => '15', + ); + my $genhelp=&Apache::loncommon::help_open_topic('Generation'); + $output = '

'.$lt{'pd'}.'

'. + &Apache::lonhtmlcommon::start_pick_box(); + foreach my $item (@userinfo) { + my $rowtitle = $lt{$item}; + my $hiderow = 0; + if ($item eq 'generation') { + $rowtitle = $genhelp.$rowtitle; + } + my $row = &Apache::lonhtmlcommon::row_title($rowtitle,undef,'LC_oddrow_value')."\n"; + if ($newuser) { + if (ref($inst_results) eq 'HASH') { + if ($inst_results->{$item} ne '') { + $row .= ''.$inst_results->{$item}; + } else { + if ($context eq 'selfcreate') { + if ($canmodify{$item}) { + $row .= ''; + $editable ++; + } else { + $hiderow = 1; + } + } else { + $row .= ''; + } + } + } else { + if ($context eq 'selfcreate') { + if (($item eq 'permanentemail') && ($newuser eq 'email')) { + $row .= $ccuname; + } else { + if ($canmodify{$item}) { + $row .= ''; + $editable ++; + } else { + $hiderow = 1; + } + } + } else { + $row .= ''; + } + } + } else { + if ($canmodify{$item}) { + $row .= ''; + } else { + $row .= $userenv{$item}; + } + if ($item eq 'id') { + $showforceid = $canmodify{$item}; + } + } + $row .= &Apache::lonhtmlcommon::row_closure(1); + if (!$hiderow) { + $output .= $row; + $rowcount ++; + } + } + if (($canmodify_status{'inststatus'}) || ($context ne 'selfcreate')) { + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($ccdomain); + if (ref($types) eq 'ARRAY') { + if (@{$types} > 0) { + my ($hiderow,$shown); + if ($canmodify_status{'inststatus'}) { + $shown = &pick_inst_statuses($userenv{'inststatus'},$usertypes,$types); + } else { + if ($userenv{'inststatus'} eq '') { + $hiderow = 1; + } else { + my @showitems; + foreach my $item ( map { &unescape($_); } split(':',$userenv{'inststatus'})) { + if (exists($usertypes->{$item})) { + push(@showitems,$usertypes->{$item}); + } else { + push(@showitems,$item); + } + } + if (@showitems) { + $shown = join(', ',@showitems); + } else { + $hiderow = 1; + } + } + } + if (!$hiderow) { + my $row = &Apache::lonhtmlcommon::row_title(&mt('Affliations'),undef,'LC_oddrow_value')."\n". + $shown.&Apache::lonhtmlcommon::row_closure(1); + if ($context eq 'selfcreate') { + $rowcount ++; + } + $output .= $row; + } + } + } + } + $output .= &Apache::lonhtmlcommon::end_pick_box(); + if (wantarray) { + if ($context eq 'selfcreate') { + return($output,$rowcount,$editable); + } else { + return ($output,$showforceid); + } } else { - $r->print(&course_level_table(%inccourses)); - $r->print('
'."\n"); + return $output; } - $r->print("".&Apache::loncommon::end_page()); +} + +sub pick_inst_statuses { + my ($curr,$usertypes,$types) = @_; + my ($output,$rem,@currtypes); + if ($curr ne '') { + @currtypes = map { &unescape($_); } split(/:/,$curr); + } + my $numinrow = 2; + if (ref($types) eq 'ARRAY') { + $output = ''; + my $lastcolspan; + for (my $i=0; $i<@{$types}; $i++) { + if (defined($usertypes->{$types->[$i]})) { + my $rem = $i%($numinrow); + if ($rem == 0) { + if ($i<@{$types}-1) { + if ($i > 0) { + $output .= ''; + } + $output .= ''; + } + } elsif ($i==@{$types}-1) { + my $colsleft = $numinrow - $rem; + if ($colsleft > 1) { + $lastcolspan = ' colspan="'.$colsleft.'"'; + } + } + my $check = ' '; + if (grep(/^\Q$types->[$i]\E$/,@currtypes)) { + $check = ' checked="checked" '; + } + $output .= ''; + } + } + $output .= '
'. + '
'; + } + return $output; +} + +sub selfcreate_canmodify { + my ($context,$dom,$userinfo,$inst_results,$rolesarray) = @_; + if (ref($inst_results) eq 'HASH') { + my @inststatuses = &get_inststatuses($inst_results); + if (@inststatuses == 0) { + @inststatuses = ('default'); + } + $rolesarray = \@inststatuses; + } + my %canmodify = + &Apache::lonuserutils::can_modify_userinfo($context,$dom,$userinfo, + $rolesarray); + return %canmodify; +} + +sub get_inststatuses { + my ($insthashref) = @_; + my @inststatuses = (); + if (ref($insthashref) eq 'HASH') { + if (ref($insthashref->{'inststatus'}) eq 'ARRAY') { + @inststatuses = @{$insthashref->{'inststatus'}}; + } + } + return @inststatuses; } # ================================================================= Phase Three sub update_user_data { - my $r=shift; + my ($r,$context,$crstype,$brcrum) = @_; my $uhome=&Apache::lonnet::homeserver($env{'form.ccuname'}, $env{'form.ccdomain'}); # Error messages - my $error = ''.&mt('Error').':'; - my $end = &Apache::loncommon::end_page(); - + my $error = ''.&mt('Error').': '; + my $end = '

'; + my $rtnlink = ''. + &mt('Return to previous page').''. + &Apache::loncommon::end_page(); + my $now = time; my $title; if (exists($env{'form.makeuser'})) { $title='Set Privileges for New User'; } else { $title='Modify User Privileges'; } - $r->print(&Apache::loncommon::start_page($title)); - my %disallowed; + my $newuser = 0; + my ($jsback,$elements) = &crumb_utilities(); + my $jscript = ''."\n"; + my %breadcrumb_text = &singleuser_breadcrumb($crstype); + push (@{$brcrum}, + {href => "javascript:backPage(document.userupdate)", + text => $breadcrumb_text{'search'}, + faq => 282, + bug => 'Instructor Interface',} + ); + if ($env{'form.prevphase'} eq 'userpicked') { + push(@{$brcrum}, + {href => "javascript:backPage(document.userupdate,'get_user_info','select')", + text => $breadcrumb_text{'userpicked'}, + faq => 282, + bug => 'Instructor Interface',}); + } + my $helpitem = 'Course_Change_Privileges'; + if ($env{'form.action'} eq 'singlestudent') { + $helpitem = 'Course_Add_Student'; + } + push(@{$brcrum}, + {href => "javascript:backPage(document.userupdate,'$env{'form.prevphase'}','modify')", + text => $breadcrumb_text{'modify'}, + faq => 282, + bug => 'Instructor Interface',}, + {href => "/adm/createuser", + text => "Result", + faq => 282, + bug => 'Instructor Interface', + help => $helpitem}); + my $args = {bread_crumbs => $brcrum, + bread_crumbs_component => 'User Management'}; + if ($env{'form.popup'}) { + $args->{'no_nav_bar'} = 1; + } + $r->print(&Apache::loncommon::start_page($title,$jscript,$args)); + $r->print(&update_result_form($uhome)); # Check Inputs if (! $env{'form.ccuname'} ) { - $r->print($error.&mt('No login name specified').'.'.$end); + $r->print($error.&mt('No login name specified').'.'.$end.$rtnlink); return; } - if ( $env{'form.ccuname'} =~/\W/) { - $r->print($error.&mt('Invalid login name').'. '. - &mt('Only letters, numbers, and underscores are valid').'.'. - $end); + if ( $env{'form.ccuname'} ne + &LONCAPA::clean_username($env{'form.ccuname'}) ) { + $r->print($error.&mt('Invalid login name.').' '. + &mt('Only letters, numbers, periods, dashes, @, and underscores are valid.'). + $end.$rtnlink); return; } if (! $env{'form.ccdomain'} ) { - $r->print($error.&mt('No domain specified').'.'.$end); + $r->print($error.&mt('No domain specified').'.'.$end.$rtnlink); return; } - if ( $env{'form.ccdomain'} =~/\W/) { - $r->print($error.&mt ('Invalid domain name').'. '. - &mt('Only letters, numbers, and underscores are valid').'.'. - $end); + if ( $env{'form.ccdomain'} ne + &LONCAPA::clean_domain($env{'form.ccdomain'}) ) { + $r->print($error.&mt('Invalid domain name.').' '. + &mt('Only letters, numbers, periods, dashes, and underscores are valid.'). + $end.$rtnlink); return; } + if ($uhome eq 'no_host') { + $newuser = 1; + } if (! exists($env{'form.makeuser'})) { # Modifying an existing user, so check the validity of the name if ($uhome eq 'no_host') { @@ -1078,21 +2307,28 @@ sub update_user_data { # If they are creating a new user but have not specified login # information this will be caught below. } else { - $r->print($error.&mt('Invalid login mode or password').$end); + $r->print($error.&mt('Invalid login mode or password').$end.$rtnlink); return; } + + $r->print('

'.&mt('User [_1] in domain [_2]', + $env{'form.ccuname'}, $env{'form.ccdomain'}).'

'); + $r->print('

'.&mt('Please be patient').'

'); + + my (%alerts,%rulematch,%inst_results,%curr_rules); + my @userinfo = ('firstname','middlename','lastname','generation','permanentemail','id'); + my @usertools = ('aboutme','blog','portfolio'); + my @requestcourses = ('official','unofficial','community'); + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($env{'form.ccdomain'}); + my %canmodify_status = + &Apache::lonuserutils::can_modify_userinfo($context,$env{'form.ccdomain'}, + ['inststatus']); if ($env{'form.makeuser'}) { - # Create a new user - my %lt=&Apache::lonlocal::texthash( - 'cru' => "Creating user", - 'id' => "in domain" - ); - $r->print(<$lt{'cru'} "$env{'form.ccuname'}" $lt{'id'} "$env{'form.ccdomain'}" -ENDNEWUSERHEAD + $r->print('

'.&mt('Creating new account.').'

'); # Check for the authentication mode and password if (! $amode || ! $genpwd) { - $r->print($error.&mt('Invalid login mode or password').$end); + $r->print($error.&mt('Invalid login mode or password').$end.$rtnlink); return; } # Determine desired host @@ -1100,37 +2336,111 @@ ENDNEWUSERHEAD if (lc($desiredhost) eq 'default') { $desiredhost = undef; } else { - my %home_servers = &Apache::loncommon::get_library_servers - ($env{'form.ccdomain'}); + my %home_servers = + &Apache::lonnet::get_servers($env{'form.ccdomain'},'library'); if (! exists($home_servers{$desiredhost})) { - $r->print($error.&mt('Invalid home server specified')); + $r->print($error.&mt('Invalid home server specified').$end.$rtnlink); return; } } + # Check ID format + my %checkhash; + my %checks = ('id' => 1); + %{$checkhash{$env{'form.ccuname'}.':'.$env{'form.ccdomain'}}} = ( + 'newuser' => $newuser, + 'id' => $env{'form.cid'}, + ); + if ($env{'form.cid'} ne '') { + &Apache::loncommon::user_rule_check(\%checkhash,\%checks,\%alerts, + \%rulematch,\%inst_results,\%curr_rules); + if (ref($alerts{'id'}) eq 'HASH') { + if (ref($alerts{'id'}{$env{'form.ccdomain'}}) eq 'HASH') { + my $domdesc = + &Apache::lonnet::domain($env{'form.ccdomain'},'description'); + if ($alerts{'id'}{$env{'form.ccdomain'}}{$env{'form.cid'}}) { + my $userchkmsg; + if (ref($curr_rules{$env{'form.ccdomain'}}) eq 'HASH') { + $userchkmsg = + &Apache::loncommon::instrule_disallow_msg('id', + $domdesc,1). + &Apache::loncommon::user_rule_formats($env{'form.ccdomain'}, + $domdesc,$curr_rules{$env{'form.ccdomain'}}{'id'},'id'); + } + $r->print($error.&mt('Invalid ID format').$end. + $userchkmsg.$rtnlink); + return; + } + } + } + } # Call modifyuser my $result = &Apache::lonnet::modifyuser - ($env{'form.ccdomain'},$env{'form.ccuname'},$env{'form.cstid'}, - $amode,$genpwd,$env{'form.cfirst'}, - $env{'form.cmiddle'},$env{'form.clast'},$env{'form.cgen'}, - undef,$desiredhost - ); + ($env{'form.ccdomain'},$env{'form.ccuname'},$env{'form.cid'}, + $amode,$genpwd,$env{'form.cfirstname'}, + $env{'form.cmiddlename'},$env{'form.clastname'}, + $env{'form.cgeneration'},undef,$desiredhost, + $env{'form.cpermanentemail'}); $r->print(&mt('Generating user').': '.$result); - my $home = &Apache::lonnet::homeserver($env{'form.ccuname'}, + $uhome = &Apache::lonnet::homeserver($env{'form.ccuname'}, $env{'form.ccdomain'}); - $r->print('
'.&mt('Home server').': '.$home.' '. - $Apache::lonnet::libserv{$home}); + my (%changeHash,%newcustom,%changed,%changedinfo); + if ($uhome ne 'no_host') { + if ($context eq 'domain') { + if ($env{'form.customquota'} == 1) { + if ($env{'form.portfolioquota'} eq '') { + $newcustom{'quota'} = 0; + } else { + $newcustom{'quota'} = $env{'form.portfolioquota'}; + $newcustom{'quota'} =~ s/[^\d\.]//g; + } + $changed{'quota'} = "a_admin($newcustom{'quota'},\%changeHash); + } + foreach my $item (@usertools) { + if ($env{'form.custom'.$item} == 1) { + $newcustom{$item} = $env{'form.tools_'.$item}; + $changed{$item} = &tool_admin($item,$newcustom{$item}, + \%changeHash,'tools'); + } + } + foreach my $item (@requestcourses) { + if ($env{'form.custom'.$item} == 1) { + $newcustom{$item} = $env{'form.crsreq_'.$item}; + if ($env{'form.crsreq_'.$item} eq 'autolimit') { + $newcustom{$item} .= '='; + unless ($env{'form.crsreq_'.$item.'_limit'} =~ /\D/) { + $newcustom{$item} .= $env{'form.crsreq_'.$item.'_limit'}; + } + } + $changed{$item} = &tool_admin($item,$newcustom{$item}, + \%changeHash,'requestcourses'); + } + } + } + if ($canmodify_status{'inststatus'}) { + if (exists($env{'form.inststatus'})) { + my @inststatuses = &Apache::loncommon::get_env_multiple('form.inststatus'); + if (@inststatuses > 0) { + $changeHash{'inststatus'} = join(',',@inststatuses); + $changed{'inststatus'} = $changeHash{'inststatus'}; + } + } + } + if (keys(%changed)) { + foreach my $item (@userinfo) { + $changeHash{$item} = $env{'form.c'.$item}; + } + my $chgresult = + &Apache::lonnet::put('environment',\%changeHash, + $env{'form.ccdomain'},$env{'form.ccuname'}); + } + } + $r->print('
'.&mt('Home server').': '.$uhome.' '. + &Apache::lonnet::hostname($uhome)); } elsif (($env{'form.login'} ne 'nochange') && ($env{'form.login'} ne '' )) { # Modify user privileges - my %lt=&Apache::lonlocal::texthash( - 'usr' => "User", - 'id' => "in domain" - ); - $r->print(<$lt{'usr'} "$env{'form.ccuname'}" $lt{'id'} "$env{'form.ccdomain'}" -ENDMODIFYUSERHEAD if (! $amode || ! $genpwd) { - $r->print($error.'Invalid login mode or password'.$end); + $r->print($error.'Invalid login mode or password'.$end.$rtnlink); return; } # Only allow authentification modification if the person has authority @@ -1143,184 +2453,827 @@ ENDMODIFYUSERHEAD ($env{'form.ccuname'},$env{'form.ccdomain'})); } else { # Okay, this is a non-fatal error. - $r->print($error.&mt('You do not have the authority to modify this users authentification information').'.'); + $r->print($error.&mt('You do not have the authority to modify this users authentification information').'.'.$end); } } + + $r->rflush(); # Finish display of header before time consuming actions start + ## + my (@userroles,%userupdate,$cnum,$cdom,%namechanged); + if ($context eq 'course') { + ($cnum,$cdom) = &Apache::lonuserutils::get_course_identity(); + $crstype = &Apache::loncommon::course_type($cdom.'_'.$cnum); + } if (! $env{'form.makeuser'} ) { # Check for need to change my %userenv = &Apache::lonnet::get ('environment',['firstname','middlename','lastname','generation', - 'portfolioquota'],$env{'form.ccdomain'},$env{'form.ccuname'}); + 'id','permanentemail','portfolioquota','inststatus','tools.aboutme', + 'tools.blog','tools.portfolio','requestcourses.official', + 'requestcourses.unofficial','requestcourses.community', + 'reqcrsotherdom.official','reqcrsotherdom.unofficial', + 'reqcrsotherdom.community'], + $env{'form.ccdomain'},$env{'form.ccuname'}); my ($tmp) = keys(%userenv); if ($tmp =~ /^(con_lost|error)/i) { %userenv = (); } - # Check to see if we need to change user information - foreach my $item ('firstname','middlename','lastname','generation') { - # Strip leading and trailing whitespace - $env{'form.c'.$item} =~ s/(\s+$|^\s+)//g; + my $no_forceid_alert; + # Check to see if user information can be changed + my %domconfig = + &Apache::lonnet::get_dom('configuration',['usermodification'], + $env{'form.ccdomain'}); + my @statuses = ('active','future'); + my %roles = &Apache::lonnet::get_my_roles($env{'form.ccuname'},$env{'form.ccdomain'},'userroles',\@statuses,undef,$env{'request.role.domain'}); + my ($auname,$audom); + if ($context eq 'author') { + $auname = $env{'user.name'}; + $audom = $env{'user.domain'}; } - my ($quotachanged,$namechanged,$oldportfolioquota); - my %changeHash; - if (exists($userenv{'portfolioquota'})) { - $oldportfolioquota = $userenv{'portfolioquota'}; - if (exists($env{'form.portfolioquota'})) { - if ($env{'form.portfolioquota'} ne $userenv{'portfolioquota'}) { - if (&Apache::lonnet::allowed('mpq',$env{'form.ccdomain'})) { - # Current user has quota modification privileges - $quotachanged = 1; - $changeHash{'portfolioquota'} = $env{'form.portfolioquota'}; + foreach my $item (keys(%roles)) { + my ($rolenum,$roledom,$role) = split(/:/,$item,-1); + if ($context eq 'course') { + if ($cnum ne '' && $cdom ne '') { + if ($rolenum eq $cnum && $roledom eq $cdom) { + if (!grep(/^\Q$role\E$/,@userroles)) { + push(@userroles,$role); + } + } + } + } elsif ($context eq 'author') { + if ($rolenum eq $auname && $roledom eq $audom) { + if (!grep(/^\Q$role\E$/,@userroles)) { + push(@userroles,$role); } } } + } + if ($env{'form.action'} eq 'singlestudent') { + if (!grep(/^st$/,@userroles)) { + push(@userroles,'st'); + } } else { - $oldportfolioquota = &default_quota($env{'form.ccdomain'}); - } - if (&Apache::lonnet::allowed('mau',$env{'form.ccdomain'}) && - ($env{'form.cfirstname'} ne $userenv{'firstname'} || - $env{'form.cmiddlename'} ne $userenv{'middlename'} || - $env{'form.clastname'} ne $userenv{'lastname'} || - $env{'form.cgeneration'} ne $userenv{'generation'} )) { - $namechanged = 1; - } - if ($namechanged) { - # Make the change - $changeHash{'firstname'} = $env{'form.cfirstname'}; - $changeHash{'middlename'} = $env{'form.cmiddlename'}; - $changeHash{'lastname'} = $env{'form.clastname'}; - $changeHash{'generation'} = $env{'form.cgeneration'}; - my $putresult = &Apache::lonnet::put - ('environment',\%changeHash, - $env{'form.ccdomain'},$env{'form.ccuname'}); - if ($putresult eq 'ok') { + # Check for course or co-author roles being activated or re-enabled + if ($context eq 'author' || $context eq 'course') { + foreach my $key (keys(%env)) { + if ($context eq 'author') { + if ($key=~/^form\.act_\Q$audom\E_\Q$auname\E_([^_]+)/) { + if (!grep(/^\Q$1\E$/,@userroles)) { + push(@userroles,$1); + } + } elsif ($key =~/^form\.ren\:\Q$audom\E\/\Q$auname\E_([^_]+)/) { + if (!grep(/^\Q$1\E$/,@userroles)) { + push(@userroles,$1); + } + } + } elsif ($context eq 'course') { + if ($key=~/^form\.act_\Q$cdom\E_\Q$cnum\E_([^_]+)/) { + if (!grep(/^\Q$1\E$/,@userroles)) { + push(@userroles,$1); + } + } elsif ($key =~/^form\.ren\:\Q$cdom\E\/\Q$cnum\E(\/?\w*)_([^_]+)/) { + if (!grep(/^\Q$1\E$/,@userroles)) { + push(@userroles,$1); + } + } + } + } + } + } + #Check to see if we can change personal data for the user + my (@mod_disallowed,@longroles); + foreach my $role (@userroles) { + if ($role eq 'cr') { + push(@longroles,'Custom'); + } else { + push(@longroles,&Apache::lonnet::plaintext($role,$crstype)); + } + } + my %canmodify = &Apache::lonuserutils::can_modify_userinfo($context,$env{'form.ccdomain'},\@userinfo,\@userroles); + foreach my $item (@userinfo) { + # Strip leading and trailing whitespace + $env{'form.c'.$item} =~ s/(\s+$|^\s+)//g; + if (!$canmodify{$item}) { + if (defined($env{'form.c'.$item})) { + if ($env{'form.c'.$item} ne $userenv{$item}) { + push(@mod_disallowed,$item); + } + } + $env{'form.c'.$item} = $userenv{$item}; + } + } + # Check to see if we can change the Student/Employee ID + my $forceid = $env{'form.forceid'}; + my $recurseid = $env{'form.recurseid'}; + my (%alerts,%rulematch,%idinst_results,%curr_rules,%got_rules); + my %uidhash = &Apache::lonnet::idrget($env{'form.ccdomain'}, + $env{'form.ccuname'}); + if (($uidhash{$env{'form.ccuname'}}) && + ($uidhash{$env{'form.ccuname'}}!~/error\:/) && + (!$forceid)) { + if ($env{'form.cid'} ne $uidhash{$env{'form.ccuname'}}) { + $env{'form.cid'} = $userenv{'id'}; + $no_forceid_alert = &mt('New student/employee ID does not match existing ID for this user.') + .'
' + .&mt("Change is not permitted without checking the 'Force ID change' checkbox on the previous page.") + .'
'."\n"; + } + } + if ($env{'form.cid'} ne $userenv{'id'}) { + my $checkhash; + my $checks = { 'id' => 1 }; + $checkhash->{$env{'form.ccuname'}.':'.$env{'form.ccdomain'}} = + { 'newuser' => $newuser, + 'id' => $env{'form.cid'}, + }; + &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'}{$env{'form.ccdomain'}}) eq 'HASH') { + $env{'form.cid'} = $userenv{'id'}; + } + } + } + my ($quotachanged,$oldportfolioquota,$newportfolioquota,$oldinststatus, + $newinststatus,$oldisdefault,$newisdefault,%oldsettings, + %oldsettingstext,%newsettings,%newsettingstext,@disporder, + $olddefquota,$oldsettingstatus,$newdefquota,$newsettingstatus); + @disporder = ('inststatus'); + if ($env{'request.role.domain'} eq $env{'form.ccdomain'}) { + push(@disporder,'requestcourses'); + } else { + push(@disporder,'reqcrsotherdom'); + } + push(@disporder,('quota','tools')); + $oldinststatus = $userenv{'inststatus'}; + ($olddefquota,$oldsettingstatus) = + &Apache::loncommon::default_quota($env{'form.ccdomain'},$oldinststatus); + ($newdefquota,$newsettingstatus) = ($olddefquota,$oldsettingstatus); + my %canshow; + if (&Apache::lonnet::allowed('mpq',$env{'form.ccdomain'})) { + $canshow{'quota'} = 1; + } + if (&Apache::lonnet::allowed('mut',$env{'form.ccdomain'})) { + $canshow{'tools'} = 1; + } + if (&Apache::lonnet::allowed('ccc',$env{'form.ccdomain'})) { + $canshow{'requestcourses'} = 1; + } elsif (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) { + $canshow{'reqcrsotherdom'} = 1; + } + if (&Apache::lonnet::allowed('mau',$env{'form.ccdomain'})) { + $canshow{'inststatus'} = 1; + } + my (%changeHash,%changed); + if ($oldinststatus eq '') { + $oldsettings{'inststatus'} = $othertitle; + } else { + if (ref($usertypes) eq 'HASH') { + $oldsettings{'inststatus'} = join(', ',map{ $usertypes->{ &unescape($_) }; } (split(/:/,$userenv{'inststatus'}))); + } else { + $oldsettings{'inststatus'} = join(', ',map{ &unescape($_); } (split(/:/,$userenv{'inststatus'}))); + } + } + $changeHash{'inststatus'} = $userenv{'inststatus'}; + if ($canmodify_status{'inststatus'}) { + $canshow{'inststatus'} = 1; + if (exists($env{'form.inststatus'})) { + my @inststatuses = &Apache::loncommon::get_env_multiple('form.inststatus'); + if (@inststatuses > 0) { + $newinststatus = join(':',map { &escape($_); } @inststatuses); + $changeHash{'inststatus'} = $newinststatus; + if ($newinststatus ne $oldinststatus) { + $changed{'inststatus'} = $newinststatus; + ($newdefquota,$newsettingstatus) = + &Apache::loncommon::default_quota($env{'form.ccdomain'},$newinststatus); + } + if (ref($usertypes) eq 'HASH') { + $newsettings{'inststatus'} = join(', ',map{ $usertypes->{$_}; } (@inststatuses)); + } else { + $newsettings{'inststatus'} = join(', ',@inststatuses); + } + } + } else { + $newinststatus = ''; + $changeHash{'inststatus'} = $newinststatus; + $newsettings{'inststatus'} = $othertitle; + if ($newinststatus ne $oldinststatus) { + $changed{'inststatus'} = $changeHash{'inststatus'}; + ($newdefquota,$newsettingstatus) = + &Apache::loncommon::default_quota($env{'form.ccdomain'},$newinststatus); + } + } + } elsif ($context ne 'selfcreate') { + $canshow{'inststatus'} = 1; + $newsettings{'inststatus'} = $oldsettings{'inststatus'}; + } + $changeHash{'portfolioquota'} = $userenv{'portfolioquota'}; + if ($context eq 'domain') { + if ($userenv{'portfolioquota'} ne '') { + $oldportfolioquota = $userenv{'portfolioquota'}; + if ($env{'form.customquota'} == 1) { + if ($env{'form.portfolioquota'} eq '') { + $newportfolioquota = 0; + } else { + $newportfolioquota = $env{'form.portfolioquota'}; + $newportfolioquota =~ s/[^\d\.]//g; + } + if ($newportfolioquota != $oldportfolioquota) { + $changed{'quota'} = "a_admin($newportfolioquota,\%changeHash); + } + } else { + $changed{'quota'} = "a_admin('',\%changeHash); + $newportfolioquota = $newdefquota; + $newisdefault = 1; + } + } else { + $oldisdefault = 1; + $oldportfolioquota = $olddefquota; + if ($env{'form.customquota'} == 1) { + if ($env{'form.portfolioquota'} eq '') { + $newportfolioquota = 0; + } else { + $newportfolioquota = $env{'form.portfolioquota'}; + $newportfolioquota =~ s/[^\d\.]//g; + } + $changed{'quota'} = "a_admin($newportfolioquota,\%changeHash); + } else { + $newportfolioquota = $newdefquota; + $newisdefault = 1; + } + } + if ($oldisdefault) { + $oldsettingstext{'quota'} = &get_defaultquota_text($oldsettingstatus); + } + if ($newisdefault) { + $newsettingstext{'quota'} = &get_defaultquota_text($newsettingstatus); + } + &tool_changes('tools',\@usertools,\%oldsettings,\%oldsettingstext,\%userenv, + \%changeHash,\%changed,\%newsettings,\%newsettingstext); + if ($env{'form.ccdomain'} eq $env{'request.role.domain'}) { + &tool_changes('requestcourses',\@requestcourses,\%oldsettings,\%oldsettingstext, + \%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext); + } else { + &tool_changes('reqcrsotherdom',\@requestcourses,\%oldsettings,\%oldsettingstext, + \%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext); + } + } + foreach my $item (@userinfo) { + if ($env{'form.c'.$item} ne $userenv{$item}) { + $namechanged{$item} = 1; + } + } + $oldsettings{'quota'} = $oldportfolioquota.' Mb'; + $newsettings{'quota'} = $newportfolioquota.' Mb'; + if ((keys(%namechanged) > 0) || (keys(%changed) > 0)) { + my ($chgresult,$namechgresult); + if (keys(%changed) > 0) { + $chgresult = + &Apache::lonnet::put('environment',\%changeHash, + $env{'form.ccdomain'},$env{'form.ccuname'}); + if ($chgresult eq 'ok') { + if (($env{'user.name'} eq $env{'form.ccuname'}) && + ($env{'user.domain'} eq $env{'form.ccdomain'})) { + my %newenvhash; + foreach my $key (keys(%changed)) { + if (($key eq 'official') || ($key eq 'unofficial') + || ($key eq 'community')) { + $newenvhash{'environment.requestcourses.'.$key} = + $changeHash{'requestcourses.'.$key}; + if ($changeHash{'requestcourses.'.$key} ne '') { + $newenvhash{'environment.canrequest.'.$key} = 1; + } else { + $newenvhash{'environment.canrequest.'.$key} = + &Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'}, + $key,'reload','requestcourses'); + } + } elsif ($key ne 'quota') { + $newenvhash{'environment.tools.'.$key} = + $changeHash{'tools.'.$key}; + if ($changeHash{'tools.'.$key} ne '') { + $newenvhash{'environment.availabletools.'.$key} = + $changeHash{'tools.'.$key}; + } else { + $newenvhash{'environment.availabletools.'.$key} = + &Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'}, $key,'reload','tools'); + } + } + } + if (keys(%newenvhash)) { + &Apache::lonnet::appenv(\%newenvhash); + } + } + } + } + if (keys(%namechanged) > 0) { + foreach my $field (@userinfo) { + $changeHash{$field} = $env{'form.c'.$field}; + } +# Make the change + $namechgresult = + &Apache::lonnet::modifyuser($env{'form.ccdomain'}, + $env{'form.ccuname'},$changeHash{'id'},undef,undef, + $changeHash{'firstname'},$changeHash{'middlename'}, + $changeHash{'lastname'},$changeHash{'generation'}, + $changeHash{'id'},undef,$changeHash{'permanentemail'},undef,\@userinfo); + %userupdate = ( + lastname => $env{'form.clastname'}, + middlename => $env{'form.cmiddlename'}, + firstname => $env{'form.cfirstname'}, + generation => $env{'form.cgeneration'}, + id => $env{'form.cid'}, + ); + } + if (((keys(%namechanged) > 0) && $namechgresult eq 'ok') || + ((keys(%changed) > 0) && $chgresult eq 'ok')) { # Tell the user we changed the name - my %lt=&Apache::lonlocal::texthash( - 'uic' => "User Information Changed", - 'frst' => "first", - 'mddl' => "middle", - 'lst' => "last", - 'gen' => "generation", - 'disk' => "disk space allocated to portfolio files", - 'prvs' => "Previous", - 'chto' => "Changed To" - ); - $r->print(<<"END"); - - - - - - - - - - - - - - - - - - - - - -
$lt{'uic'}
 $lt{'frst'}$lt{'mddl'}$lt{'lst'}$lt{'gen'}$lt{'disk'}
$lt{'prvs'}$userenv{'firstname'} $userenv{'middlename'} $userenv{'lastname'} $userenv{'generation'} $oldportfolioquota
$lt{'chto'}$env{'form.cfirstname'} $env{'form.cmiddlename'} $env{'form.clastname'} $env{'form.cgeneration'} $env{'form.portfolioquota'} Mb
-END + &display_userinfo($r,1,\@disporder,\%canshow,\@requestcourses, + \@usertools,\%userenv,\%changed,\%namechanged, + \%oldsettings, \%oldsettingstext,\%newsettings, + \%newsettingstext); + if ($env{'form.cid'} ne $userenv{'id'}) { + &Apache::lonnet::idput($env{'form.ccdomain'}, + ($env{'form.ccuname'} => $env{'form.cid'})); + if (($recurseid) && + (&Apache::lonnet::allowed('mau',$env{'form.ccdomain'}))) { + my $idresult = + &Apache::lonuserutils::propagate_id_change( + $env{'form.ccuname'},$env{'form.ccdomain'}, + \%userupdate); + $r->print('
'.$idresult.'
'); + } + } + if (($env{'form.ccdomain'} eq $env{'user.domain'}) && + ($env{'form.ccuname'} eq $env{'user.name'})) { + my %newenvhash; + foreach my $key (keys(%changeHash)) { + $newenvhash{'environment.'.$key} = $changeHash{$key}; + } + &Apache::lonnet::appenv(\%newenvhash); + } } else { # error occurred - $r->print("

".&mt('Unable to successfully change environment for')." ". - $env{'form.ccuname'}." ".&mt('in domain')." ". - $env{'form.ccdomain'}."

"); - } - } else { # End of if ($env ... ) logic - my $putresult; - if ($quotachanged) { - $putresult = &Apache::lonnet::put - ('environment',\%changeHash, - $env{'form.ccdomain'},$env{'form.ccuname'}); + $r->print(''.&mt('Unable to successfully change environment for').' '. + $env{'form.ccuname'}.' '.&mt('in domain').' '. + $env{'form.ccdomain'}.'
'); } - # They did not want to change the users name but we can - # still tell them what the name is - my %lt=&Apache::lonlocal::texthash( - 'usr' => "User", - 'id' => "in domain", - 'gen' => "Generation", - 'disk' => "Disk space allocated to user's portfolio files", - ); - $r->print(<<"END"); -

$lt{'usr'} "$env{'form.ccuname'}" $lt{'id'} "$env{'form.ccdomain'}"

-

$userenv{'firstname'} $userenv{'middlename'} $userenv{'lastname'}

-

$lt{'gen'}: $userenv{'generation'}

-END - if ($putresult eq 'ok') { - if ($oldportfolioquota ne $env{'form.portfolioquota'}) { - $r->print('

'.$lt{'disk'}.': '.$env{'form.portfolioquota'}.' Mb

'); + } else { # End of if ($env ... ) logic + # They did not want to change the users name, quota, tool availability, + # or ability to request creation of courses, + # but we can still tell them what the name and quota and availabilities are + &display_userinfo($r,undef,\@disporder,\%canshow,\@requestcourses, + \@usertools,\%userenv,\%changed,\%namechanged,\%oldsettings, + \%oldsettingstext,\%newsettings,\%newsettingstext); + } + if (@mod_disallowed) { + my ($rolestr,$contextname); + if (@longroles > 0) { + $rolestr = join(', ',@longroles); + } else { + $rolestr = &mt('No roles'); + } + if ($context eq 'course') { + $contextname = &mt('course'); + } elsif ($context eq 'author') { + $contextname = &mt('co-author'); + } + $r->print(&mt('The following fields were not updated: ').'
    '); + my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); + foreach my $field (@mod_disallowed) { + $r->print('
  • '.$fieldtitles{$field}.'
  • '."\n"); + } + $r->print('
'); + if (@mod_disallowed == 1) { + $r->print(&mt("You do not have the authority to change this field given the user's current set of active/future [_1] roles:",$contextname)); + } else { + $r->print(&mt("You do not have the authority to change these fields given the user's current set of active/future [_1] roles:",$contextname)); + } + my $helplink = 'javascript:helpMenu('."'display'".')'; + $r->print(''.$rolestr.'
' + .&mt('Please contact your [_1]helpdesk[_2] for more information.' + ,'','') + .'
'); + } + $r->print('' + .$no_forceid_alert + .&Apache::lonuserutils::print_namespacing_alerts($env{'form.ccdomain'},\%alerts,\%curr_rules) + .''); + } + if ($env{'form.action'} eq 'singlestudent') { + &enroll_single_student($r,$uhome,$amode,$genpwd,$now,$newuser,$context,$crstype); + $r->print('

'); + if ($crstype eq 'Community') { + $r->print(&mt('Enroll Another Member')); + } else { + $r->print(&mt('Enroll Another Student')); + } + $r->print('

'); + } else { + my @rolechanges = &update_roles($r,$context); + if (keys(%namechanged) > 0) { + if ($context eq 'course') { + if (@userroles > 0) { + if ((@rolechanges == 0) || + (!(grep(/^st$/,@rolechanges)))) { + if (grep(/^st$/,@userroles)) { + my $classlistupdated = + &Apache::lonuserutils::update_classlist($cdom, + $cnum,$env{'form.ccdomain'}, + $env{'form.ccuname'},\%userupdate); + } + } } } } + my $userinfo = &Apache::loncommon::plainname($env{'form.ccuname'}, + $env{'form.ccdomain'}); + if ($env{'form.popup'}) { + $r->print('

'.&mt('Close window').'

'); + } else { + $r->print('

' + .&mt('Modify this user: [_1]',''.$env{'form.ccuname'}.':'.$env{'form.ccdomain'}.' ('.$userinfo.')').'' + .(' 'x5).'' + .&mt('Create/Modify Another User').'

'); + } } - ## +} + +sub display_userinfo { + my ($r,$changed,$order,$canshow,$requestcourses,$usertools,$userenv, + $changedhash,$namechangedhash,$oldsetting,$oldsettingtext, + $newsetting,$newsettingtext) = @_; + return unless (ref($order) eq 'ARRAY' && + ref($canshow) eq 'HASH' && + ref($requestcourses) eq 'ARRAY' && + ref($usertools) eq 'ARRAY' && + ref($userenv) eq 'HASH' && + ref($changedhash) eq 'HASH' && + ref($oldsetting) eq 'HASH' && + ref($oldsettingtext) eq 'HASH' && + ref($newsetting) eq 'HASH' && + ref($newsettingtext) eq 'HASH'); + my %lt=&Apache::lonlocal::texthash( + 'ui' => 'User Information (unchanged)', + 'uic' => 'User Information Changed', + 'firstname' => 'First Name', + 'middlename' => 'Middle Name', + 'lastname' => 'Last Name', + 'generation' => 'Generation', + 'id' => 'Student/Employee ID', + 'permanentemail' => 'Permanent e-mail address', + 'quota' => 'Disk space allocated to portfolio files', + 'blog' => 'Blog Availability', + 'aboutme' => 'Personal Information Page Availability', + 'portfolio' => 'Portfolio Availability', + 'official' => 'Can Request Official Courses', + 'unofficial' => 'Can Request Unofficial Courses', + 'community' => 'Can Request Communities', + 'inststatus' => "Affiliation", + 'prvs' => 'Previous Value:', + 'chto' => 'Changed To:' + ); + my $title = $lt{'ui'}; + if ($changed) { + $title = $lt{'uic'}; + } + $r->print('

'.$title.'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row()); + if ($changed) { + $r->print(" \n"); + } + my @userinfo = ('firstname','middlename','lastname','generation','permanentemail','id'); + foreach my $item (@userinfo) { + $r->print("$lt{$item}\n"); + } + foreach my $entry (@{$order}) { + if ($canshow->{$entry}) { + if (($entry eq 'requestcourses') || ($entry eq 'reqcrsotherdom')) { + foreach my $item (@{$requestcourses}) { + $r->print("$lt{$item}\n"); + } + } elsif ($entry eq 'tools') { + foreach my $item (@{$usertools}) { + $r->print("$lt{$item}\n"); + } + } else { + $r->print("$lt{$entry}\n"); + } + } + } + $r->print(&Apache::loncommon::end_data_table_header_row(). + &Apache::loncommon::start_data_table_row()); + if ($changed) { + $r->print(''.$lt{'prvs'}.''."\n"); + } + foreach my $item (@userinfo) { + $r->print(''.$userenv->{$item}.' '."\n"); + } + foreach my $entry (@{$order}) { + if ($canshow->{$entry}) { + if (($entry eq 'requestcourses') || ($entry eq 'reqcrsotherdom')) { + foreach my $item (@{$requestcourses}) { + $r->print("$oldsetting->{$item} $oldsettingtext->{$item}\n"); + } + } elsif ($entry eq 'tools') { + foreach my $item (@{$usertools}) { + $r->print("$oldsetting->{$item} $oldsettingtext->{$item}\n"); + } + } else { + $r->print("$oldsetting->{$entry} $oldsettingtext->{$entry} \n"); + } + } + } + $r->print(&Apache::loncommon::end_data_table_row()); + if ($changed) { + $r->print(&Apache::loncommon::start_data_table_row(). + ''.$lt{'chto'}.''."\n"); + foreach my $item (@userinfo) { + my $value = $env{'form.c'.$item}; + if ($namechangedhash->{$item}) { + $value = ''.$value.''; + } + $r->print("$value \n"); + } + foreach my $entry (@{$order}) { + if ($canshow->{$entry}) { + if (($entry eq 'requestcourses') || ($entry eq 'reqcrsotherdom')) { + foreach my $item (@{$requestcourses}) { + my $value = $newsetting->{$item}.' '.$newsettingtext->{$item}; + if ($changedhash->{$item}) { + $value = ''.$value.''; + } + $r->print("$value \n"); + } + } elsif ($entry eq 'tools') { + foreach my $item (@{$usertools}) { + my $value = $newsetting->{$item}.' '.$newsettingtext->{$item}; + if ($changedhash->{$item}) { + $value = ''.$value.''; + } + $r->print("$value \n"); + } + } else { + my $value = $newsetting->{$entry}.' '.$newsettingtext->{$entry}; + if ($changedhash->{$entry}) { + $value = ''.$value.''; + } + $r->print("$value \n"); + } + } + } + $r->print(&Apache::loncommon::end_data_table_row()); + } + $r->print(&Apache::loncommon::end_data_table().'
'); + return; +} + +sub tool_changes { + my ($context,$usertools,$oldaccess,$oldaccesstext,$userenv,$changeHash, + $changed,$newaccess,$newaccesstext) = @_; + if (!((ref($usertools) eq 'ARRAY') && (ref($oldaccess) eq 'HASH') && + (ref($oldaccesstext) eq 'HASH') && (ref($userenv) eq 'HASH') && + (ref($changeHash) eq 'HASH') && (ref($changed) eq 'HASH') && + (ref($newaccess) eq 'HASH') && (ref($newaccesstext) eq 'HASH'))) { + return; + } + if ($context eq 'reqcrsotherdom') { + my @options = ('approval','validate','autolimit'); + my $optregex = join('|',@options); + my %reqdisplay = &courserequest_display(); + my $cdom = $env{'request.role.domain'}; + foreach my $tool (@{$usertools}) { + $oldaccesstext->{$tool} = &mt('No'); + $newaccesstext->{$tool} = $oldaccesstext->{$tool}; + $changeHash->{$context.'.'.$tool} = $userenv->{$context.'.'.$tool}; + my $newop; + if ($env{'form.'.$context.'_'.$tool}) { + $newop = $env{'form.'.$context.'_'.$tool}; + if ($newop eq 'autolimit') { + my $limit = $env{'form.'.$context.'_'.$tool.'_limit'}; + $limit =~ s/\D+//g; + $newop .= '='.$limit; + } + } + if ($userenv->{$context.'.'.$tool} eq '') { + if ($newop) { + $changed->{$tool}=&tool_admin($tool,$cdom.':'.$newop, + $changeHash,$context); + if ($changed->{$tool}) { + $newaccesstext->{$tool} = &mt('Yes'); + } else { + $newaccesstext->{$tool} = $oldaccesstext->{$tool}; + } + } + } else { + my @curr = split(',',$userenv->{$context.'.'.$tool}); + my @new; + my $changedoms; + foreach my $req (@curr) { + if ($req =~ /^\Q$cdom\E\:($optregex\=?\d*)$/) { + $oldaccesstext->{$tool} = &mt('Yes'); + my $oldop = $1; + if ($oldop ne $newop) { + $changedoms = 1; + foreach my $item (@curr) { + my ($reqdom,$option) = split(':',$item); + unless ($reqdom eq $cdom) { + push(@new,$item); + } + } + if ($newop) { + push(@new,$cdom.':'.$newop); + } + @new = sort(@new); + } + last; + } + } + if ((!$changedoms) && ($newop)) { + $changedoms = 1; + @new = sort(@curr,$cdom.':'.$newop); + } + if ($changedoms) { + my $newdomstr; + if (@new) { + $newdomstr = join(',',@new); + } + $changed->{$tool}=&tool_admin($tool,$newdomstr,$changeHash, + $context); + if ($changed->{$tool}) { + if ($env{'form.'.$context.'_'.$tool}) { + if ($env{'form.'.$context.'_'.$tool} eq 'autolimit') { + my $limit = $env{'form.'.$context.'_'.$tool.'_limit'}; + $limit =~ s/\D+//g; + if ($limit) { + $newaccesstext->{$tool} = &mt('Yes, up to limit of [quant,_1,request] per user.',$limit); + } else { + $newaccesstext->{$tool} = &mt('Yes, processed automatically'); + } + } else { + $newaccesstext->{$tool} = $reqdisplay{$env{'form.'.$context.'_'.$tool}}; + } + } else { + $newaccesstext->{$tool} = &mt('No'); + } + } + } + } + } + return; + } + foreach my $tool (@{$usertools}) { + my $newval; + if ($context eq 'requestcourses') { + $newval = $env{'form.crsreq_'.$tool}; + if ($newval eq 'autolimit') { + $newval .= '='.$env{'form.crsreq_'.$tool.'_limit'}; + } + } else { + $newval = $env{'form.'.$context.'_'.$tool}; + } + if ($userenv->{$context.'.'.$tool} ne '') { + $oldaccess->{$tool} = &mt('custom'); + if ($userenv->{$context.'.'.$tool}) { + $oldaccesstext->{$tool} = &mt("availability set to 'on'"); + } else { + $oldaccesstext->{$tool} = &mt("availability set to 'off'"); + } + $changeHash->{$context.'.'.$tool} = $userenv->{$context.'.'.$tool}; + if ($env{'form.custom'.$tool} == 1) { + if ($newval ne $userenv->{$context.'.'.$tool}) { + $changed->{$tool} = &tool_admin($tool,$newval,$changeHash, + $context); + if ($changed->{$tool}) { + $newaccess->{$tool} = &mt('custom'); + if ($newval) { + $newaccesstext->{$tool} = &mt("availability set to 'on'"); + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } else { + $newaccess->{$tool} = $oldaccess->{$tool}; + if ($userenv->{$context.'.'.$tool}) { + $newaccesstext->{$tool} = &mt("availability set to 'on'"); + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } + } else { + $newaccess->{$tool} = $oldaccess->{$tool}; + $newaccesstext->{$tool} = $oldaccesstext->{$tool}; + } + } else { + $changed->{$tool} = &tool_admin($tool,'',$changeHash,$context); + if ($changed->{$tool}) { + $newaccess->{$tool} = &mt('default'); + } else { + $newaccess->{$tool} = $oldaccess->{$tool}; + if ($userenv->{$context.'.'.$tool}) { + $newaccesstext->{$tool} = &mt("availability set to 'on'"); + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } + } + } else { + $oldaccess->{$tool} = &mt('default'); + if ($env{'form.custom'.$tool} == 1) { + $changed->{$tool} = &tool_admin($tool,$newval,$changeHash, + $context); + if ($changed->{$tool}) { + $newaccess->{$tool} = &mt('custom'); + if ($newval) { + $newaccesstext->{$tool} = &mt("availability set to 'on'"); + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } else { + $newaccess->{$tool} = $oldaccess->{$tool}; + } + } else { + $newaccess->{$tool} = $oldaccess->{$tool}; + } + } + } + return; +} + +sub update_roles { + my ($r,$context) = @_; my $now=time; + my @rolechanges; + my %disallowed; $r->print('

'.&mt('Modifying Roles').'

'); foreach my $key (keys (%env)) { next if (! $env{$key}); + next if ($key eq 'form.action'); # Revoke roles if ($key=~/^form\.rev/) { if ($key=~/^form\.rev\:([^\_]+)\_([^\_\.]+)$/) { # Revoke standard role - $r->print(&mt('Revoking').' '.$2.' in '.$1.': '. - &Apache::lonnet::revokerole($env{'form.ccdomain'}, - $env{'form.ccuname'},$1,$2).'
'); - if ($2 eq 'st') { - $1=~/^\/(\w+)\/(\w+)/; - my $cid=$1.'_'.$2; - $r->print(&mt('Drop from classlist').': '. - &Apache::lonnet::critical('put:'. - $env{'course.'.$cid.'.domain'}.':'. - $env{'course.'.$cid.'.num'}.':classlist:'. - &escape($env{'form.ccuname'}.':'. - $env{'form.ccdomain'}).'='. - &escape($now.':'), - $env{'course.'.$cid.'.home'}).'
'); + my ($scope,$role) = ($1,$2); + my $result = + &Apache::lonnet::revokerole($env{'form.ccdomain'}, + $env{'form.ccuname'}, + $scope,$role,'','',$context); + $r->print(&mt('Revoking [_1] in [_2]: [_3]', + $role,$scope,''.$result.'').'
'); + if ($role eq 'st') { + my $result = + &Apache::lonuserutils::classlist_drop($scope, + $env{'form.ccuname'},$env{'form.ccdomain'}, + $now); + $r->print($result); } - } - if ($key=~/^form\.rev\:([^\_]+)\_cr\.cr\/(\w+)\/(\w+)\/(\w+)$/) { + if (!grep(/^\Q$role\E$/,@rolechanges)) { + push(@rolechanges,$role); + } + } + if ($key=~m{^form\.rev\:([^_]+)_cr\.cr/($match_domain)/($match_username)/(\w+)$}s) { # Revoke custom role $r->print(&mt('Revoking custom role:'). - ' '.$4.' by '.$3.'@'.$2.' in '.$1.': '. + ' '.$4.' by '.$3.':'.$2.' in '.$1.': '. &Apache::lonnet::revokecustomrole($env{'form.ccdomain'}, - $env{'form.ccuname'},$1,$2,$3,$4). + $env{'form.ccuname'},$1,$2,$3,$4,'','',$context). '
'); + if (!grep(/^cr$/,@rolechanges)) { + push(@rolechanges,'cr'); + } } } elsif ($key=~/^form\.del/) { if ($key=~/^form\.del\:([^\_]+)\_([^\_\.]+)$/) { # Delete standard role - $r->print(&mt('Deleting').' '.$2.' in '.$1.': '. - &Apache::lonnet::assignrole($env{'form.ccdomain'}, - $env{'form.ccuname'},$1,$2,$now,0,1).'
'); - if ($2 eq 'st') { - $1=~/^\/(\w+)\/(\w+)/; - my $cid=$1.'_'.$2; - $r->print(&mt('Drop from classlist').': '. - &Apache::lonnet::critical('put:'. - $env{'course.'.$cid.'.domain'}.':'. - $env{'course.'.$cid.'.num'}.':classlist:'. - &escape($env{'form.ccuname'}.':'. - $env{'form.ccdomain'}).'='. - &escape($now.':'), - $env{'course.'.$cid.'.home'}).'
'); + my ($scope,$role) = ($1,$2); + my $result = + &Apache::lonnet::assignrole($env{'form.ccdomain'}, + $env{'form.ccuname'}, + $scope,$role,$now,0,1,'', + $context); + $r->print(&mt('Deleting [_1] in [_2]: [_3]',$role,$scope, + ''.$result.'').'
'); + if ($role eq 'st') { + my $result = + &Apache::lonuserutils::classlist_drop($scope, + $env{'form.ccuname'},$env{'form.ccdomain'}, + $now); + $r->print($result); } + if (!grep(/^\Q$role\E$/,@rolechanges)) { + push(@rolechanges,$role); + } } - if ($key=~/^form\.del\:([^\_]+)\_cr\.cr\/(\w+)\/(\w+)\/(\w+)$/) { + if ($key=~m{^form\.del\:([^_]+)_cr\.cr/($match_domain)/($match_username)/(\w+)$}) { my ($url,$rdom,$rnam,$rolename) = ($1,$2,$3,$4); # Delete custom role - $r->print(&mt('Deleting custom role [_1] by [_2]@[_3] in [_4]', - $rolename,$rnam,$rdom,$url).': '. + $r->print(&mt('Deleting custom role [_1] by [_2] in [_3]', + $rolename,$rnam.':'.$rdom,$url).': '. &Apache::lonnet::assigncustomrole($env{'form.ccdomain'}, $env{'form.ccuname'},$url,$rdom,$rnam,$rolename,$now, - 0,1).'
'); + 0,1,$context).'

'); + if (!grep(/^cr$/,@rolechanges)) { + push(@rolechanges,'cr'); + } } } elsif ($key=~/^form\.ren/) { my $udom = $env{'form.ccdomain'}; @@ -1332,10 +3285,14 @@ END my $logmsg; my $output; if ($role eq 'st') { - if ($url =~ m-^/(\w+)/(\w+)/?(\w*)$-) { + if ($url =~ m-^/($match_domain)/($match_courseid)/?(\w*)$-) { my $result = &Apache::loncommon::commit_studentrole(\$logmsg,$udom,$uname,$url,$role,$now,0,$1,$2,$3); - if (($result =~ /^error/) || ($result eq 'not_in_class') || ($result eq 'unknown_course')) { - $output = "Error: $result\n"; + if (($result =~ /^error/) || ($result eq 'not_in_class') || ($result eq 'unknown_course') || ($result eq 'refused')) { + if ($result eq 'refused' && $logmsg) { + $output = $logmsg; + } else { + $output = "Error: $result\n"; + } } else { $output = &mt('Assigning').' '.$role.' in '.$url. &mt('starting').' '.localtime($now). @@ -1345,25 +3302,32 @@ END } } else { my $result=&Apache::lonnet::assignrole($env{'form.ccdomain'}, - $env{'form.ccuname'},$url,$role,0,$now); - $output = &mt('Re-enabling [_1] in [_2]: [_3]', - $role,$url,$result).'
'; + $env{'form.ccuname'},$url,$role,0,$now,'','', + $context); + $output = &mt('Re-enabling [_1] in [_2]: [_3]', + $role,$url,''.$result.'').'
'; } $r->print($output); + if (!grep(/^\Q$role\E$/,@rolechanges)) { + push(@rolechanges,$role); + } } # Re-enable custom role - if ($key=~/^form\.ren\:([^\_]+)\_cr\.cr\/(\w+)\/(\w+)\/(\w+)$/) { + if ($key=~m{^form\.ren\:([^_]+)_cr\.cr/($match_domain)/($match_username)/(\w+)$}) { my ($url,$rdom,$rnam,$rolename) = ($1,$2,$3,$4); my $result = &Apache::lonnet::assigncustomrole( $env{'form.ccdomain'}, $env{'form.ccuname'}, - $url,$rdom,$rnam,$rolename,0,$now); - $r->print(&mt('Re-enabling custom role [_1] by [_2]@[_3] in [_4] : [_5]', - $rolename,$rnam,$rdom,$url,$result).'
'); + $url,$rdom,$rnam,$rolename,0,$now,undef,$context); + $r->print(&mt('Re-enabling custom role [_1] by [_2] in [_3]: [_4]', + $rolename,$rnam.':'.$rdom,$url,''.$result.'').'
'); + if (!grep(/^cr$/,@rolechanges)) { + push(@rolechanges,'cr'); + } } } elsif ($key=~/^form\.act/) { my $udom = $env{'form.ccdomain'}; my $uname = $env{'form.ccuname'}; - if ($key=~/^form\.act\_([^\_]+)\_([^\_]+)\_cr_cr_([^\_]+)_(\w+)_([^\_]+)$/) { + if ($key=~/^form\.act\_($match_domain)\_($match_courseid)\_cr_cr_($match_domain)_($match_username)_([^\_]+)$/) { # Activate a custom role my ($one,$two,$three,$four,$five)=($1,$2,$3,$4,$5); my $url='/'.$one.'/'.$two; @@ -1380,7 +3344,7 @@ END my %sections = (); my $num_sections = &build_roles($env{'form.sec_'.$full},\%sections,$5); if ($num_sections == 0) { - $r->print(&Apache::loncommon::commit_customrole($udom,$uname,$url,$three,$four,$five,$start,$end)); + $r->print(&Apache::loncommon::commit_customrole($udom,$uname,$url,$three,$four,$five,$start,$end,$context)); } else { my %curr_groups = &Apache::longroup::coursegroups($one,$two); @@ -1391,10 +3355,13 @@ END next; } my $securl = $url.'/'.$sec; - $r->print(&Apache::loncommon::commit_customrole($udom,$uname,$securl,$three,$four,$five,$start,$end)); + $r->print(&Apache::loncommon::commit_customrole($udom,$uname,$securl,$three,$four,$five,$start,$end,$context)); } } - } elsif ($key=~/^form\.act\_([^\_]+)\_(\w+)\_([^\_]+)$/) { + if (!grep(/^cr$/,@rolechanges)) { + push(@rolechanges,'cr'); + } + } elsif ($key=~/^form\.act\_($match_domain)\_($match_name)\_([^\_]+)$/) { # Activate roles for sections with 3 id numbers # set start, end times, and the url for the class my ($one,$two,$three)=($1,$2,$3); @@ -1410,7 +3377,7 @@ END my %sections = (); my $num_sections = &build_roles($env{'form.sec_'.$one.'_'.$two.'_'.$three},\%sections,$three); if ($num_sections == 0) { - $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$three,$start,$end,$one,$two,'')); + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$three,$start,$end,$one,$two,'',$context)); } else { my %curr_groups = &Apache::longroup::coursegroups($one,$two); @@ -1424,15 +3391,18 @@ END next; } my $securl = $url.'/'.$sec; - $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$securl,$three,$start,$end,$one,$two,$sec)); + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$securl,$three,$start,$end,$one,$two,$sec,$context)); } else { $emptysec = 1; } } if ($emptysec) { - $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$three,$start,$end,$one,$two,'')); + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$three,$start,$end,$one,$two,'',$context)); } - } + } + if (!grep(/^\Q$three\E$/,@rolechanges)) { + push(@rolechanges,$three); + } } elsif ($key=~/^form\.act\_([^\_]+)\_([^\_]+)$/) { # Activate roles for sections with two id numbers # set start, end times, and the url for the class @@ -1442,43 +3412,191 @@ END my $end = ( $env{'form.end_'.$1.'_'.$2} ? $env{'form.end_'.$1.'_'.$2} : 0 ); - my $url='/'.$1.'/'; + my $one = $1; + my $two = $2; + my $url='/'.$one.'/'; # split multiple sections my %sections = (); - my $num_sections = &build_roles($env{'form.sec_'.$1.'_'.$2},\%sections,$2); + my $num_sections = &build_roles($env{'form.sec_'.$one.'_'.$two},\%sections,$two); if ($num_sections == 0) { - $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$2,$start,$end,$1,undef,'')); + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$two,$start,$end,$one,undef,'',$context)); } else { my $emptysec = 0; foreach my $sec (sort {$a cmp $b} keys %sections) { if ($sec ne '') { my $securl = $url.'/'.$sec; - $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$securl,$2,$start,$end,$1,undef,$sec)); + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$securl,$two,$start,$end,$one,undef,$sec,$context)); } else { $emptysec = 1; } } if ($emptysec) { - $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$2,$start,$end,$1,undef,'')); + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$two,$start,$end,$one,undef,'',$context)); } } + if (!grep(/^\Q$two\E$/,@rolechanges)) { + push(@rolechanges,$two); + } } else { - $r->print('

'.&mt('ERROR').': '.&mt('Unknown command').' '.$key.'


'); + $r->print('

'.&mt('ERROR').': '.&mt('Unknown command').' '.$key.'


'); } foreach my $key (sort(keys(%disallowed))) { + $r->print('

'); if (($key eq 'none') || ($key eq 'all')) { - $r->print('

'.&mt('[_1] may not be used as the name for a section, as it is a reserved word.',$key)); + $r->print(&mt('[_1] may not be used as the name for a section, as it is a reserved word.',''.$key.'')); } else { - $r->print('

'.&mt('[_1] may not be used as the name for a section, as it is the name of a course group.',$key)); + $r->print(&mt('[_1] may not be used as the name for a section, as it is the name of a course group.',''.$key.'')); } - $r->print(' '.&mt('Please go back and choose a different section name.').'


'); + $r->print('

' + .&mt('Please [_1]go back[_2] and choose a different section name.' + ,'Create/Modify Another User

'); - $r->print(&Apache::loncommon::end_page()); + $r->register_cleanup(\&Apache::lonnet::flushcourselogs); + if (@rolechanges == 0) { + $r->print(&mt('No roles to modify')); + } + return @rolechanges; +} + +sub enroll_single_student { + my ($r,$uhome,$amode,$genpwd,$now,$newuser,$context,$crstype) = @_; + $r->print('

'); + if ($crstype eq 'Community') { + $r->print(&mt('Enrolling Member')); + } else { + $r->print(&mt('Enrolling Student')); + } + $r->print('

'); + + # Remove non alphanumeric values from section + $env{'form.sections'}=~s/\W//g; + + # Clean out any old student roles the user has in this class. + &Apache::lonuserutils::modifystudent($env{'form.ccdomain'}, + $env{'form.ccuname'},$env{'request.course.id'},undef,$uhome); + my ($startdate,$enddate) = &Apache::lonuserutils::get_dates_from_form(); + my $enroll_result = + &Apache::lonnet::modify_student_enrollment($env{'form.ccdomain'}, + $env{'form.ccuname'},$env{'form.cid'},$env{'form.cfirstname'}, + $env{'form.cmiddlename'},$env{'form.clastname'}, + $env{'form.generation'},$env{'form.sections'},$enddate, + $startdate,'manual',undef,$env{'request.course.id'},'',$context); + if ($enroll_result =~ /^ok/) { + $r->print(&mt('[_1] enrolled',$env{'form.ccuname'}.':'.$env{'form.ccdomain'})); + if ($env{'form.sections'} ne '') { + $r->print(' '.&mt('in section [_1]',$env{'form.sections'})); + } + my ($showstart,$showend); + if ($startdate <= $now) { + $showstart = &mt('Access starts immediately'); + } else { + $showstart = &mt('Access starts: ').&Apache::lonlocal::locallocaltime($startdate); + } + if ($enddate == 0) { + $showend = &mt('ends: no ending date'); + } else { + $showend = &mt('ends: ').&Apache::lonlocal::locallocaltime($enddate); + } + $r->print('.
'.$showstart.'; '.$showend); + if ($startdate <= $now && !$newuser) { + $r->print('

'); + if ($crstype eq 'Community') { + $r->print(&mt('If the member is currently logged-in to LON-CAPA, the new role will be available when the member next logs in.')); + } else { + $r->print(&mt('If the student is currently logged-in to LON-CAPA, the new role will be available when the student next logs in.')); + } + $r->print('

'); + } + } else { + $r->print(&mt('unable to enroll').": ".$enroll_result); + } + return; +} + +sub get_defaultquota_text { + my ($settingstatus) = @_; + my $defquotatext; + if ($settingstatus eq '') { + $defquotatext = &mt('(default)'); + } else { + my ($usertypes,$order) = + &Apache::lonnet::retrieve_inst_usertypes($env{'form.ccdomain'}); + if ($usertypes->{$settingstatus} eq '') { + $defquotatext = &mt('(default)'); + } else { + $defquotatext = &mt('(default for [_1])',$usertypes->{$settingstatus}); + } + } + return $defquotatext; +} + +sub update_result_form { + my ($uhome) = @_; + my $outcome = + '
'."\n"; + foreach my $item ('srchby','srchin','srchtype','srchterm','srchdomain','ccuname','ccdomain') { + $outcome .= ''."\n"; + } + if ($env{'form.origname'} ne '') { + $outcome .= ''."\n"; + } + foreach my $item ('sortby','seluname','seludom') { + if (exists($env{'form.'.$item})) { + $outcome .= ''."\n"; + } + } + if ($uhome eq 'no_host') { + $outcome .= ''."\n"; + } + $outcome .= ''."\n". + ''."\n". + ''."\n". + '
'; + return $outcome; +} + +sub quota_admin { + my ($setquota,$changeHash) = @_; + my $quotachanged; + if (&Apache::lonnet::allowed('mpq',$env{'form.ccdomain'})) { + # Current user has quota modification privileges + if (ref($changeHash) eq 'HASH') { + $quotachanged = 1; + $changeHash->{'portfolioquota'} = $setquota; + } + } + return $quotachanged; +} + +sub tool_admin { + my ($tool,$settool,$changeHash,$context) = @_; + my $canchange = 0; + if ($context eq 'requestcourses') { + if (&Apache::lonnet::allowed('ccc',$env{'form.ccdomain'})) { + $canchange = 1; + } + } elsif ($context eq 'reqcrsotherdom') { + if (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) { + $canchange = 1; + } + } elsif (&Apache::lonnet::allowed('mut',$env{'form.ccdomain'})) { + # Current user has quota modification privileges + $canchange = 1; + } + my $toolchanged; + if ($canchange) { + if (ref($changeHash) eq 'HASH') { + $toolchanged = 1; + $changeHash->{$context.'.'.$tool} = $settool; + } + } + return $toolchanged; } sub build_roles { @@ -1493,7 +3611,7 @@ sub build_roles { } else { foreach my $sec (@secnums) { $sec =~ ~s/\W//g; - unless ($sec eq "") { + if (!($sec eq "")) { if (exists($$sections{$sec})) { $$sections{$sec} ++; } else { @@ -1517,44 +3635,57 @@ sub build_roles { # ========================================================== Custom Role Editor sub custom_role_editor { - my $r=shift; - my $rolename=$env{'form.rolename'}; + my ($r,$brcrum) = @_; + my $action = $env{'form.customroleaction'}; + my $rolename; + if ($action eq 'new') { + $rolename=$env{'form.newrolename'}; + } else { + $rolename=$env{'form.rolename'}; + } - if ($rolename eq 'make new role') { - $rolename=$env{'form.newrolename'}; + my ($crstype,$context); + if ($env{'request.course.id'}) { + $crstype = &Apache::loncommon::course_type(); + $context = 'course'; + } else { + $context = 'domain'; + $crstype = $env{'form.templatecrstype'}; } $rolename=~s/[^A-Za-z0-9]//gs; - - unless ($rolename) { - &print_username_entry_form($r); + if (!$rolename || $env{'form.phase'} eq 'pickrole') { + &print_username_entry_form($r,undef,undef,undef,undef,$crstype,$brcrum); return; } - $r->print(&Apache::loncommon::start_page('Custom Role Editor')); +# ------------------------------------------------------- What can be assigned? + my %full=(); + my %courselevel=(); + my %courselevelcurrent=(); my $syspriv=''; my $dompriv=''; my $coursepriv=''; + my $body_top; my ($rdummy,$roledef)= &Apache::lonnet::get('roles',["rolesdef_$rolename"]); # ------------------------------------------------------- Does this role exist? - $r->print('

'); + $body_top .= '

'; if (($rdummy ne 'con_lost') && ($roledef ne '')) { - $r->print(&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//; + } } else { - $r->print(&mt('New Role').' "'); + $body_top .= &mt('New Role').' "'; $roledef=''; } - $r->print($rolename.'"

'); -# ------------------------------------------------------- What can be assigned? - my %full=(); - my %courselevel=(); - my %courselevelcurrent=(); + $body_top .= $rolename.'"'; foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) { my ($priv,$restrict)=split(/\&/,$item); - unless ($restrict) { $restrict='F'; } + if (!$restrict) { $restrict='F'; } $courselevel{$priv}=$restrict; if ($coursepriv=~/\:$priv/) { $courselevelcurrent{$priv}=1; @@ -1565,7 +3696,7 @@ sub custom_role_editor { my %domainlevelcurrent=(); foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) { my ($priv,$restrict)=split(/\&/,$item); - unless ($restrict) { $restrict='F'; } + if (!$restrict) { $restrict='F'; } $domainlevel{$priv}=$restrict; if ($dompriv=~/\:$priv/) { $domainlevelcurrent{$priv}=1; @@ -1576,21 +3707,105 @@ sub custom_role_editor { my %systemlevelcurrent=(); foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) { my ($priv,$restrict)=split(/\&/,$item); - unless ($restrict) { $restrict='F'; } + if (!$restrict) { $restrict='F'; } $systemlevel{$priv}=$restrict; if ($syspriv=~/\:$priv/) { $systemlevelcurrent{$priv}=1; } $full{$priv}=1; } + my ($jsback,$elements) = &crumb_utilities(); + my $button_code = "\n"; + my $head_script = "\n"; + $head_script .= ''."\n"; + push (@{$brcrum}, + {href => "javascript:backPage(document.form1,'pickrole','')", + text => "Pick custom role", + faq => 282,bug=>'Instructor Interface',}, + {href => "javascript:backPage(document.form1,'','')", + text => "Edit custom role", + faq => 282, + bug => 'Instructor Interface', + help => 'Course_Editing_Custom_Roles'} + ); + 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" - ); + 'ssl' => "System Level"); + + $r->print('
' + .'
' + .''.&mt('Select a Template').'' + .$button_code + .'
'); + if ($context_code) { + $r->print('
' + .'
' + .''.&mt('Context').'' + .$context_code + .'' + .'
' + ); + } + $r->print('
'); + $r->print(< +
ENDCCF @@ -1599,51 +3814,152 @@ ENDCCF ''.$lt{'prv'}.''.$lt{'crl'}.''.$lt{'dml'}. ''.$lt{'ssl'}.''. &Apache::loncommon::end_data_table_header_row()); - foreach my $priv (sort keys %full) { - my $privtext = &Apache::lonnet::plaintext($priv); + foreach my $priv (sort(keys(%full))) { + my $privtext = &Apache::lonnet::plaintext($priv,$crstype); $r->print(&Apache::loncommon::start_data_table_row(). ''.$privtext.''. - ($courselevel{$priv}?'':' '). - ''. - ($domainlevel{$priv}?'':' '). + ($courselevel{$priv}?'':' '). ''. - ($systemlevel{$priv}?'':' '). - ''. - &Apache::loncommon::end_data_table_row()); + ($domainlevel{$priv}?'':' '). + ''); + if ($priv eq 'bre' && $crstype eq 'Community') { + $r->print(' '); + } else { + $r->print($systemlevel{$priv}?'':' '); + } + $r->print(''. + &Apache::loncommon::end_data_table_row()); } $r->print(&Apache::loncommon::end_data_table(). - '
'. - &Apache::loncommon::end_page()); + ''. + ''."\n".''."\n". + ''."\n". + ''); +} +# -------------------------------------------------------- +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 = ''; + return ($button_code); } - # ---------------------------------------------------------- Call to definerole sub set_custom_role { - my ($r) = @_; - + my ($r,$context,$brcrum) = @_; my $rolename=$env{'form.rolename'}; - $rolename=~s/[^A-Za-z0-9]//gs; - - unless ($rolename) { - &print_username_entry_form($r); + if (!$rolename) { + &custom_role_editor($r,$brcrum); return; } + my ($jsback,$elements) = &crumb_utilities(); + my $jscript = ''."\n"; + push(@{$brcrum}, + {href => "javascript:backPage(document.customresult,'pickrole','')", + text => "Pick custom role", + faq => 282, + bug => 'Instructor Interface',}, + {href => "javascript:backPage(document.customresult,'selected_custom_edit','')", + text => "Edit custom role", + faq => 282, + bug => 'Instructor Interface',}, + {href => "javascript:backPage(document.customresult,'set_custom_roles','')", + text => "Result", + faq => 282, + bug => 'Instructor Interface', + help => 'Course_Editing_Custom_Roles'}, + ); + my $args = { bread_crumbs => $brcrum, + bread_crumbs_component => 'User Management'}; + $r->print(&Apache::loncommon::start_page('Save Custom Role',$jscript,$args)); - $r->print(&Apache::loncommon::start_page('Save Custom Role').'

'); my ($rdummy,$roledef)= &Apache::lonnet::get('roles',["rolesdef_$rolename"]); # ------------------------------------------------------- Does this role exist? + $r->print('

'); if (($rdummy ne 'con_lost') && ($roledef ne '')) { $r->print(&mt('Existing Role').' "'); } else { $r->print(&mt('New Role').' "'); $roledef=''; } - $r->print($rolename.'"

'); + $r->print($rolename.'"'); # ------------------------------------------------------- What can be assigned? my $sysrole=''; my $domrole=''; @@ -1651,24 +3967,24 @@ sub set_custom_role { foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) { my ($priv,$restrict)=split(/\&/,$item); - unless ($restrict) { $restrict=''; } - if ($env{'form.'.$priv.':c'}) { + if (!$restrict) { $restrict=''; } + if ($env{'form.'.$priv.'_c'}) { $courole.=':'.$item; } } foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) { my ($priv,$restrict)=split(/\&/,$item); - unless ($restrict) { $restrict=''; } - if ($env{'form.'.$priv.':d'}) { + if (!$restrict) { $restrict=''; } + if ($env{'form.'.$priv.'_d'}) { $domrole.=':'.$item; } } foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) { my ($priv,$restrict)=split(/\&/,$item); - unless ($restrict) { $restrict=''; } - if ($env{'form.'.$priv.':s'}) { + if (!$restrict) { $restrict=''; } + if ($env{'form.'.$priv.'_s'}) { $sysrole.=':'.$item; } } @@ -1683,57 +3999,2088 @@ sub set_custom_role { $url, $env{'user.domain'}, $env{'user.name'}, - $rolename)); + $rolename,undef,undef,undef,$context)); } - $r->print('

Create another role, or Create/Modify a user.

'); - $r->print(&Apache::loncommon::end_page()); + $r->print('

'.&mt('Create or edit another custom role').'

'); + $r->print(&Apache::lonhtmlcommon::echo_form_input([]).'
'); } # ================================================================ Main Handler sub handler { my $r = shift; - if ($r->header_only) { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK; } + my ($context,$crstype); + if ($env{'request.course.id'}) { + $context = 'course'; + $crstype = &Apache::loncommon::course_type(); + } elsif ($env{'request.role'} =~ /^au\./) { + $context = 'author'; + } else { + $context = 'domain'; + } + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['action','state','callingform','roletype','showrole','bulkaction','popup','phase', + 'username','domain','srchterm','srchdomain','srchin','srchby','srchtype']); + &Apache::lonhtmlcommon::clear_breadcrumbs(); + my $args; + my $brcrum = []; + my $bread_crumbs_component = 'User Management'; + if ($env{'form.action'} ne 'dateselect') { + $brcrum = [{href=>"/adm/createuser", + text=>"User Management", + help=>'Course_Create_Class_List,Course_Change_Privileges,Course_View_Class_List,Course_Editing_Custom_Roles,Course_Add_Student,Course_Drop_Student,Course_Automated_Enrollment,Course_Self_Enrollment,Course_Manage_Group'} + ]; + } + #SD Following files not added to help, because the corresponding .tex-files seem to + #be missing: Course_Approve_Selfenroll,Course_User_Logs, + my ($permission,$allowed) = + &Apache::lonuserutils::get_permission($context,$crstype); + if (!$allowed) { + $env{'user.error.msg'}= + "/adm/createuser:cst:0:0:Cannot create/modify user data ". + "or view user status."; + return HTTP_NOT_ACCEPTABLE; + } + + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + + # Main switch on form.action and form.state, as appropriate + if (! exists($env{'form.action'})) { + $args = {bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + $r->print(&header(undef,$args)); + $r->print(&print_main_menu($permission,$context,$crstype)); + } elsif ($env{'form.action'} eq 'upload' && $permission->{'cusr'}) { + push(@{$brcrum}, + { href => '/adm/createuser?action=upload&state=', + text => 'Upload Users List', + help => 'Course_Create_Class_List', + }); + $bread_crumbs_component = 'Upload Users List'; + $args = {bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + $r->print(&header(undef,$args)); + $r->print('
'."\n"); + if (! exists($env{'form.state'})) { + &Apache::lonuserutils::print_first_users_upload_form($r,$context); + } elsif ($env{'form.state'} eq 'got_file') { + &Apache::lonuserutils::print_upload_manager_form($r,$context, + $permission,$crstype); + } elsif ($env{'form.state'} eq 'enrolling') { + if ($env{'form.datatoken'}) { + &Apache::lonuserutils::upfile_drop_add($r,$context,$permission); + } + } else { + &Apache::lonuserutils::print_first_users_upload_form($r,$context); + } + } elsif ((($env{'form.action'} eq 'singleuser') || ($env{'form.action'} + eq 'singlestudent')) && ($permission->{'cusr'})) { + my $phase = $env{'form.phase'}; + my @search = ('srchterm','srchby','srchin','srchtype','srchdomain'); + &Apache::loncreateuser::restore_prev_selections(); + my $srch; + foreach my $item (@search) { + $srch->{$item} = $env{'form.'.$item}; + } + if (($phase eq 'get_user_info') || ($phase eq 'userpicked') || + ($phase eq 'createnewuser')) { + if ($env{'form.phase'} eq 'createnewuser') { + my $response; + if ($env{'form.srchterm'} !~ /^$match_username$/) { + my $response = &mt('You must specify a valid username. Only the following are allowed: letters numbers - . @'); + $env{'form.phase'} = ''; + &print_username_entry_form($r,$context,$response,$srch,undef,$crstype,$brcrum); + } else { + my $ccuname =&LONCAPA::clean_username($srch->{'srchterm'}); + my $ccdomain=&LONCAPA::clean_domain($srch->{'srchdomain'}); + &print_user_modification_page($r,$ccuname,$ccdomain, + $srch,$response,$context, + $permission,$crstype,$brcrum); + } + } elsif ($env{'form.phase'} eq 'get_user_info') { + my ($currstate,$response,$forcenewuser,$results) = + &user_search_result($context,$srch); + if ($env{'form.currstate'} eq 'modify') { + $currstate = $env{'form.currstate'}; + } + if ($currstate eq 'select') { + &print_user_selection_page($r,$response,$srch,$results, + \@search,$context,undef,$crstype, + $brcrum); + } elsif ($currstate eq 'modify') { + my ($ccuname,$ccdomain); + if (($srch->{'srchby'} eq 'uname') && + ($srch->{'srchtype'} eq 'exact')) { + $ccuname = $srch->{'srchterm'}; + $ccdomain= $srch->{'srchdomain'}; + } else { + my @matchedunames = keys(%{$results}); + ($ccuname,$ccdomain) = split(/:/,$matchedunames[0]); + } + $ccuname =&LONCAPA::clean_username($ccuname); + $ccdomain=&LONCAPA::clean_domain($ccdomain); + if ($env{'form.forcenewuser'}) { + $response = ''; + } + &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 { + $env{'form.phase'} = ''; + &print_username_entry_form($r,$context,$response,$srch, + $forcenewuser,$crstype,$brcrum); + } + } 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); + } + } elsif ($env{'form.phase'} eq 'update_user_data') { + &update_user_data($r,$context,$crstype,$brcrum); + } else { + &print_username_entry_form($r,$context,undef,$srch,undef,$crstype, + $brcrum); + } + } elsif ($env{'form.action'} eq 'custom' && $permission->{'custom'}) { + if ($env{'form.phase'} eq 'set_custom_roles') { + &set_custom_role($r,$context,$brcrum); + } else { + &custom_role_editor($r,$brcrum); + } + } elsif (($env{'form.action'} eq 'listusers') && + ($permission->{'view'} || $permission->{'cusr'})) { + if ($env{'form.phase'} eq 'bulkchange') { + push(@{$brcrum}, + {href => '/adm/createuser?action=listusers', + text => "List Users"}, + {href => "/adm/createuser", + text => "Result", + help => 'Course_View_Class_List'}); + $bread_crumbs_component = 'Update Users'; + $args = {bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + $r->print(&header(undef,$args)); + my $setting = $env{'form.roletype'}; + my $choice = $env{'form.bulkaction'}; + if ($permission->{'cusr'}) { + &Apache::lonuserutils::update_user_list($r,$context,$setting,$choice,$crstype); + } else { + $r->print(&mt('You are not authorized to make bulk changes to user roles')); + $r->print('

'.&mt('Display User Lists').''); + } + } else { + push(@{$brcrum}, + {href => '/adm/createuser?action=listusers', + text => "List Users", + help => 'Course_View_Class_List'}); + $bread_crumbs_component = 'List Users'; + $args = {bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + my ($cb_jscript,$jscript,$totcodes,$codetitles,$idlist,$idlist_titles); + my $formname = 'studentform'; + if (($context eq 'domain') && (($env{'form.roletype'} eq 'course') || + ($env{'form.roletype'} eq 'community'))) { + if ($env{'form.roletype'} eq 'course') { + ($cb_jscript,$jscript,$totcodes,$codetitles,$idlist,$idlist_titles) = + &Apache::lonuserutils::courses_selector($env{'request.role.domain'}, + $formname); + } elsif ($env{'form.roletype'} eq 'community') { + $cb_jscript = + &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'}); + my %elements = ( + coursepick => 'radio', + coursetotal => 'text', + courselist => 'text', + ); + $jscript = &Apache::lonhtmlcommon::set_form_elements(\%elements); + } + $jscript .= &verify_user_display(); + my $js = &add_script($jscript).$cb_jscript; + my $loadcode = + &Apache::lonuserutils::course_selector_loadcode($formname); + if ($loadcode ne '') { + $args->{add_entries} = {onload => $loadcode}; + } + $r->print(&header($js,$args)); + } else { + $r->print(&header(&add_script(&verify_user_display()),$args)); + } + &Apache::lonuserutils::print_userlist($r,undef,$permission,$context, + $formname,$totcodes,$codetitles,$idlist,$idlist_titles); + } + } elsif ($env{'form.action'} eq 'drop' && $permission->{'cusr'}) { + my $brtext; + if ($crstype eq 'Community') { + $brtext = 'Drop Members'; + } else { + $brtext = 'Drop Students'; + } + push(@{$brcrum}, + {href => '/adm/createuser?action=drop', + text => $brtext, + help => 'Course_Drop_Student'}); + if ($env{'form.state'} eq 'done') { + push(@{$brcrum}, + {href=>'/adm/createuser?action=drop', + text=>"Result"}); + } + $bread_crumbs_component = $brtext; + $args = {bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + $r->print(&header(undef,$args)); + if (!exists($env{'form.state'})) { + &Apache::lonuserutils::print_drop_menu($r,$context,$permission,$crstype); + } elsif ($env{'form.state'} eq 'done') { + &Apache::lonuserutils::update_user_list($r,$context,undef, + $env{'form.action'}); + } + } elsif ($env{'form.action'} eq 'dateselect') { + if ($permission->{'cusr'}) { + $r->print(&header(undef,{'no_nav_bar' => 1}). + &Apache::lonuserutils::date_section_selector($context, + $permission,$crstype)); + } else { + $r->print(&header(undef,{'no_nav_bar' => 1}). + ''.&mt('You do not have permission to modify dates or sections for users').''); + } + } elsif ($env{'form.action'} eq 'selfenroll') { + push(@{$brcrum}, + {href => '/adm/createuser?action=selfenroll', + text => "Configure Self-enrollment", + help => 'Course_Self_Enrollment'}); + if (!exists($env{'form.state'})) { + $args = { bread_crumbs => $brcrum, + bread_crumbs_component => 'Configure Self-enrollment'}; + $r->print(&header(undef,$args)); + $r->print('

'.&mt('Self-enrollment with a student role').'

'."\n"); + &print_selfenroll_menu($r,$context,$permission); + } elsif ($env{'form.state'} eq 'done') { + push (@{$brcrum}, + {href=>'/adm/createuser?action=selfenroll', + text=>"Result"}); + $args = { bread_crumbs => $brcrum, + bread_crumbs_component => 'Self-enrollment result'}; + $r->print(&header(undef,$args)); + $r->print('

'.&mt('Self-enrollment with a student role').'

'."\n"); + &update_selfenroll_config($r,$context,$permission); + } + } elsif ($env{'form.action'} eq 'selfenrollqueue') { + push(@{$brcrum}, + {href => '/adm/createuser?action=selfenrollqueue', + text => 'Enrollment requests', + help => 'Course_Self_Enrollment'}); + $bread_crumbs_component = 'Enrollment requests'; + if ($env{'form.state'} eq 'done') { + push(@{$brcrum}, + {href => '/adm/createuser?action=selfenrollqueue', + text => 'Result', + help => 'Course_Self_Enrollment'}); + $bread_crumbs_component = 'Enrollment result'; + } + $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + $r->print(&header(undef,$args)); + my $cid = $env{'request.course.id'}; + my $cdom = $env{'course.'.$cid.'.domain'}; + my $cnum = $env{'course.'.$cid.'.num'}; + my $coursedesc = $env{'course.'.$cid.'.description'}; + if (!exists($env{'form.state'})) { + $r->print('

'.&mt('Pending enrollment requests').'

'."\n"); + $r->print(&Apache::loncoursequeueadmin::display_queued_requests($context, + $cdom,$cnum)); + } elsif ($env{'form.state'} eq 'done') { + $r->print('

'.&mt('Enrollment request processing').'

'."\n"); + $r->print(&Apache::loncoursequeueadmin::update_request_queue($context, + $cdom,$cnum,$coursedesc)); + } + } elsif ($env{'form.action'} eq 'changelogs') { + push (@{$brcrum}, + {href => '/adm/createuser?action=changelogs', + text => 'User Management Logs', + help => 'Course_User_Logs'}); + $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); + } else { + $bread_crumbs_component = 'User Management'; + $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + $r->print(&header(undef,$args)); + $r->print(&print_main_menu($permission,$context,$crstype)); + } + $r->print(&Apache::loncommon::end_page()); + return OK; +} - if ((&Apache::lonnet::allowed('cta',$env{'request.course.id'})) || - (&Apache::lonnet::allowed('cin',$env{'request.course.id'})) || - (&Apache::lonnet::allowed('ccr',$env{'request.course.id'})) || - (&Apache::lonnet::allowed('cep',$env{'request.course.id'})) || - (&authorpriv($env{'user.name'},$env{'request.role.domain'})) || - (&Apache::lonnet::allowed('mau',$env{'request.role.domain'}))) { - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; - unless ($env{'form.phase'}) { - &print_username_entry_form($r); - } - if ($env{'form.phase'} eq 'get_user_info') { - &print_user_modification_page($r); - } elsif ($env{'form.phase'} eq 'update_user_data') { - &update_user_data($r); - } elsif ($env{'form.phase'} eq 'selected_custom_edit') { - &custom_role_editor($r); - } elsif ($env{'form.phase'} eq 'set_custom_roles') { - &set_custom_role($r); - } - } else { - $env{'user.error.msg'}= - "/adm/createuser:mau:0:0:Cannot modify user data"; - return HTTP_NOT_ACCEPTABLE; - } - return OK; -} +sub header { + my ($jscript,$args) = @_; + my $start_page; + if (ref($args) eq 'HASH') { + $start_page=&Apache::loncommon::start_page('User Management',$jscript,$args); + } else { + $start_page=&Apache::loncommon::start_page('User Management',$jscript); + } + return $start_page; +} + +sub add_script { + my ($js) = @_; + return ''."\n"; +} + +sub verify_user_display { + my $output = <<"END"; + +function display_update() { + document.studentform.action.value = 'listusers'; + document.studentform.phase.value = 'display'; + document.studentform.submit(); +} + +END + return $output; + +} + +############################################################### +############################################################### +# Menu Phase One +sub print_main_menu { + my ($permission,$context,$crstype) = @_; + my $linkcontext = $context; + my $stuterm = lc(&Apache::lonnet::plaintext('st',$crstype)); + if (($context eq 'course') && ($crstype eq 'Community')) { + $linkcontext = lc($crstype); + $stuterm = 'Members'; + } + my %links = ( + domain => { + upload => 'Upload a File of Users', + singleuser => 'Add/Modify a User', + listusers => 'Manage Users', + }, + author => { + upload => 'Upload a File of Co-authors', + singleuser => 'Add/Modify a Co-author', + listusers => 'Manage Co-authors', + }, + course => { + upload => 'Upload a File of Course Users', + singleuser => 'Add/Modify a Course User', + listusers => 'Manage Course Users', + }, + community => { + upload => 'Upload a File of Community Users', + singleuser => 'Add/Modify a Community User', + listusers => 'Manage Community Users', + }, + ); + my %linktitles = ( + domain => { + singleuser => 'Add a user to the domain, and/or a course or community in the domain.', + listusers => 'Show and manage users in this domain.', + }, + author => { + singleuser => 'Add a user with a co- or assistant author role.', + listusers => 'Show and manage co- or assistant authors.', + }, + course => { + singleuser => 'Add a user with a certain role to this course.', + listusers => 'Show and manage users in this course.', + }, + community => { + singleuser => 'Add a user with a certain role to this community.', + listusers => 'Show and manage users in this community.', + }, + ); + my @menu = ( {categorytitle => 'Single Users', + items => + [ + { + linktext => $links{$linkcontext}{'singleuser'}, + icon => 'edit-redo.png', + #help => 'Course_Change_Privileges', + url => '/adm/createuser?action=singleuser', + permission => $permission->{'cusr'}, + linktitle => $linktitles{$linkcontext}{'singleuser'}, + }, + ]}, + + {categorytitle => 'Multiple Users', + items => + [ + { + linktext => $links{$linkcontext}{'upload'}, + icon => 'uplusr.png', + #help => 'Course_Create_Class_List', + url => '/adm/createuser?action=upload', + permission => $permission->{'cusr'}, + linktitle => 'Upload a CSV or a text file containing users.', + }, + { + linktext => $links{$linkcontext}{'listusers'}, + icon => 'mngcu.png', + #help => 'Course_View_Class_List', + url => '/adm/createuser?action=listusers', + permission => ($permission->{'view'} || $permission->{'cusr'}), + linktitle => $linktitles{$linkcontext}{'listusers'}, + }, + + ]}, + + {categorytitle => 'Administration', + items => [ ]}, + ); + + if ($context eq 'domain'){ + + push(@{ $menu[2]->{items} }, #Category: Administration + { + linktext => 'Custom Roles', + icon => 'emblem-photos.png', + #help => 'Course_Editing_Custom_Roles', + url => '/adm/createuser?action=custom', + permission => $permission->{'custom'}, + linktitle => 'Configure a custom role.', + }, + ); + + }elsif ($context eq 'course'){ + my ($cnum,$cdom) = &Apache::lonuserutils::get_course_identity(); + + my %linktext = ( + 'Course' => { + single => 'Add/Modify a Student', + drop => 'Drop Students', + groups => 'Course Groups', + }, + 'Community' => { + single => 'Add/Modify a Member', + drop => 'Drop Members', + groups => 'Community Groups', + }, + ); + + my %linktitle = ( + 'Course' => { + single => 'Add a user with the role of student to this course', + drop => 'Remove a student from this course.', + groups => 'Manage course groups', + }, + 'Community' => { + single => 'Add a user with the role of member to this community', + drop => 'Remove a member from this community.', + groups => 'Manage community groups', + }, + ); + + push(@{ $menu[0]->{items} }, #Category: Single Users + { + linktext => $linktext{$crstype}{'single'}, + #help => 'Course_Add_Student', + icon => 'list-add.png', + url => '/adm/createuser?action=singlestudent', + permission => $permission->{'cusr'}, + linktitle => $linktitle{$crstype}{'single'}, + }, + ); + + push(@{ $menu[1]->{items} }, #Category: Multiple Users + { + linktext => $linktext{$crstype}{'drop'}, + icon => 'edit-undo.png', + #help => 'Course_Drop_Student', + url => '/adm/createuser?action=drop', + permission => $permission->{'cusr'}, + linktitle => $linktitle{$crstype}{'drop'}, + }, + ); + push(@{ $menu[2]->{items} }, #Category: Administration + { + linktext => 'Custom Roles', + icon => 'emblem-photos.png', + #help => 'Course_Editing_Custom_Roles', + url => '/adm/createuser?action=custom', + permission => $permission->{'custom'}, + linktitle => 'Configure a custom role.', + }, + { + linktext => $linktext{$crstype}{'groups'}, + icon => 'grps.png', + #help => 'Course_Manage_Group', + url => '/adm/coursegroups?refpage=cusr', + permission => $permission->{'grp_manage'}, + linktitle => $linktitle{$crstype}{'groups'}, + }, + { + linktext => 'Change Log', + icon => 'document-properties.png', + #help => 'Course_User_Logs', + url => '/adm/createuser?action=changelogs', + permission => $permission->{'cusr'}, + linktitle => 'View change log.', + }, + ); + if ($env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_approval'}) { + push(@{ $menu[2]->{items} }, + { + linktext => 'Enrollment Requests', + icon => 'selfenrl-queue.png', + #help => 'Course_Approve_Selfenroll', + url => '/adm/createuser?action=selfenrollqueue', + permission => $permission->{'cusr'}, + linktitle =>'Approve or reject enrollment requests.', + }, + ); + } + + if (!exists($permission->{'cusr_section'})){ + if ($crstype ne 'Community') { + push(@{ $menu[2]->{items} }, + { + linktext => 'Automated Enrollment', + icon => 'roles.png', + #help => 'Course_Automated_Enrollment', + permission => (&Apache::lonnet::auto_run($cnum,$cdom) + && $permission->{'cusr'}), + url => '/adm/populate', + linktitle => 'Automated enrollment manager.', + } + ); + } + push(@{ $menu[2]->{items} }, + { + linktext => 'User Self-Enrollment', + icon => 'self_enroll.png', + #help => 'Course_Self_Enrollment', + url => '/adm/createuser?action=selfenroll', + permission => $permission->{'cusr'}, + linktitle => 'Configure user self-enrollment.', + }, + ); + } + }; +return Apache::lonhtmlcommon::generate_menu(@menu); +# { text => 'View Log-in History', +# help => 'Course_User_Logins', +# action => 'logins', +# permission => $permission->{'cusr'}, +# }); +} + +sub restore_prev_selections { + my %saveable_parameters = ('srchby' => 'scalar', + 'srchin' => 'scalar', + 'srchtype' => 'scalar', + ); + &Apache::loncommon::store_settings('user','user_picker', + \%saveable_parameters); + &Apache::loncommon::restore_settings('user','user_picker', + \%saveable_parameters); +} + +sub print_selfenroll_menu { + my ($r,$context,$permission) = @_; + my $crstype = &Apache::loncommon::course_type(); + my $formname = 'enrollstudent'; + my $nolink = 1; + my ($row,$lt) = &get_selfenroll_titles(); + my $groupslist = &Apache::lonuserutils::get_groupslist(); + my $setsec_js = + &Apache::lonuserutils::setsections_javascript($formname,$groupslist); + my %alerts = &Apache::lonlocal::texthash( + acto => 'Activation of self-enrollment was selected for the following domain(s)', + butn => 'but no user types have been checked.', + wilf => "Please uncheck 'activate' or check at least one type.", + ); + my $selfenroll_js = <<"ENDSCRIPT"; +function update_types(caller,num) { + var delidx = getIndexByName('selfenroll_delete'); + var actidx = getIndexByName('selfenroll_activate'); + if (caller == 'selfenroll_all') { + var selall; + for (var i=0; i 0) { + var msg = "$alerts{'acto'}\\n"; + var loopend = needaction.length -1; + if (loopend > 0) { + for (var m=0; m'."\n". + ''."\n". + '

'.$lt->{'selfenroll'}.'

'."\n"; + my ($visible,$cansetvis,$vismsgs,$visactions) = &visible_in_cat($cdom,$cnum); + if (ref($visactions) eq 'HASH') { + if ($visible) { + $output .= '

'.$visactions->{'vis'}.'

'; + } else { + $output .= '

'.$visactions->{'miss'}.'

' + .$visactions->{'yous'}. + '

'.$visactions->{'gen'}.'
'.$visactions->{'coca'}; + if (ref($vismsgs) eq 'ARRAY') { + $output .= '
'.$visactions->{'make'}.'

    '; + foreach my $item (@{$vismsgs}) { + $output .= '
  • '.$visactions->{$item}.'
  • '; + } + $output .= '
'; + } + $output .= '

'; + } + } + $output .= ''."\n". + &Apache::lonhtmlcommon::start_pick_box(); + if (ref($row) eq 'ARRAY') { + foreach my $item (@{$row}) { + my $title = $item; + if (ref($lt) eq 'HASH') { + $title = $lt->{$item}; + } + $output .= &Apache::lonhtmlcommon::row_title($title); + if ($item eq 'types') { + my $curr_types = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_types'}; + my $showdomdesc = 1; + my $includeempty = 1; + my $num = 0; + $output .= &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row() + .''. + '  '.&mt('No').''. + &Apache::loncommon::end_data_table_row(). + &Apache::loncommon::end_data_table(). + &mt('Or').'
'. + &Apache::loncommon::start_data_table(); + my %currdoms; + if ($curr_types eq '') { + $output .= &new_selfenroll_dom_row($cdom,'0'); + } elsif ($curr_types ne '*') { + my @entries = split(/;/,$curr_types); + if (@entries > 0) { + foreach my $entry (@entries) { + my ($currdom,$typestr) = split(/:/,$entry); + $currdoms{$currdom} = 1; + my $domdesc = &Apache::lonnet::domain($currdom); + my @currinsttypes = split(',',$typestr); + $output .= &Apache::loncommon::start_data_table_row() + .''.&mt('Domain:').'' + .' '.$domdesc.' ('.$currdom.')' + .'
' + .''; + $output .= '  '.&mt('User types:').'
' + .&selfenroll_inst_types($num,$currdom,\@currinsttypes).'' + .&Apache::loncommon::end_data_table_row(); + $num ++; + } + } + } + my $add_domtitle = &mt('Users in additional domain:'); + if ($curr_types eq '*') { + $add_domtitle = &mt('Users in specific domain:'); + } elsif ($curr_types eq '') { + $add_domtitle = &mt('Users in other domain:'); + } + $output .= &Apache::loncommon::start_data_table_row() + .''.$add_domtitle.'
' + .&Apache::loncommon::select_dom_form('','selfenroll_newdom', + $includeempty,$showdomdesc) + .'' + .''.&Apache::loncommon::end_data_table_row() + .&Apache::loncommon::end_data_table(); + } elsif ($item eq 'registered') { + my ($regon,$regoff); + if ($env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_registered'}) { + $regon = ' checked="checked" '; + $regoff = ' '; + } else { + $regon = ' '; + $regoff = ' checked="checked" '; + } + $output .= '  '; + } elsif ($item eq 'enroll_dates') { + my $starttime = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_start_date'}; + my $endtime = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_end_date'}; + if ($starttime eq '') { + $starttime = $env{'course.'.$env{'request.course.id'}.'.default_enrollment_start_date'}; + } + if ($endtime eq '') { + $endtime = $env{'course.'.$env{'request.course.id'}.'.default_enrollment_end_date'}; + } + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_start_date',$starttime, + undef,undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_end_date',$endtime, + undef,undef,undef,undef,undef,undef,undef,$nolink); + $output .= &selfenroll_date_forms($startform,$endform); + } elsif ($item eq 'access_dates') { + my $starttime = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_start_access'}; + my $endtime = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_end_access'}; + if ($starttime eq '') { + $starttime = $env{'course.'.$env{'request.course.id'}.'.default_enrollment_start_date'}; + } + if ($endtime eq '') { + $endtime = $env{'course.'.$env{'request.course.id'}.'.default_enrollment_end_date'}; + } + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_start_access',$starttime, + undef,undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_end_access',$endtime, + undef,undef,undef,undef,undef,undef,undef,$nolink); + $output .= &selfenroll_date_forms($startform,$endform); + } elsif ($item eq 'section') { + my $currsec = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_section'}; + my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum); + my $newsecval; + if ($currsec ne 'none' && $currsec ne '') { + if (!defined($sections_count{$currsec})) { + $newsecval = $currsec; + } + } + my $sections_select = + &Apache::lonuserutils::course_sections(\%sections_count,'st',$currsec); + $output .= ''."\n". + ''."\n". + '
'.&mt('Existing sections')."\n". + '
'.$sections_select.'
'. + &mt('New section').'
'."\n". + ''."\n". + ''."\n". + ''."\n". + '
'."\n"; + } elsif ($item eq 'approval') { + my ($appon,$appoff); + my $cid = $env{'request.course.id'}; + my $currnotified = $env{'course.'.$cid.'.internal.selfenroll_notifylist'}; + if ($env{'course.'.$cid.'.internal.selfenroll_approval'}) { + $appon = ' checked="checked" '; + $appoff = ' '; + } else { + $appon = ' '; + $appoff = ' checked="checked" '; + } + $output .= '  '; + my %advhash = &Apache::lonnet::get_course_adv_roles($cid,1); + my (@ccs,%notified); + my $ccrole = 'cc'; + if ($crstype eq 'Community') { + $ccrole = 'co'; + } + if ($advhash{$ccrole}) { + @ccs = split(/,/,$advhash{$ccrole}); + } + if ($currnotified) { + foreach my $current (split(/,/,$currnotified)) { + $notified{$current} = 1; + if (!grep(/^\Q$current\E$/,@ccs)) { + push(@ccs,$current); + } + } + } + if (@ccs) { + $output .= '
'.&mt('Personnel to be notified when an enrollment request needs approval, or has been approved:').' '.&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(); + my $count = 0; + my $numcols = 4; + foreach my $cc (sort(@ccs)) { + my $notifyon; + my ($ccuname,$ccudom) = split(/:/,$cc); + if ($notified{$cc}) { + $notifyon = ' checked="checked" '; + } + if ($count && !$count%$numcols) { + $output .= &Apache::loncommon::end_data_table_row(). + &Apache::loncommon::start_data_table_row() + } + $output .= ''; + $count ++; + } + my $rem = $count%$numcols; + if ($rem) { + my $emptycols = $numcols - $rem; + for (my $i=0; $i<$emptycols; $i++) { + $output .= ' '; + } + } + $output .= &Apache::loncommon::end_data_table_row(). + &Apache::loncommon::end_data_table(); + } + } elsif ($item eq 'limit') { + my ($crslimit,$selflimit,$nolimit); + my $cid = $env{'request.course.id'}; + my $currlim = $env{'course.'.$cid.'.internal.selfenroll_limit'}; + my $currcap = $env{'course.'.$cid.'.internal.selfenroll_cap'}; + $nolimit = ' checked="checked" '; + if ($currlim eq 'allstudents') { + $crslimit = ' checked="checked" '; + $selflimit = ' '; + $nolimit = ' '; + } elsif ($currlim eq 'selfenrolled') { + $crslimit = ' '; + $selflimit = ' checked="checked" '; + $nolimit = ' '; + } else { + $crslimit = ' '; + $selflimit = ' '; + } + $output .= ''. + '
 '. + (' 'x3).&mt('Maximum number allowed: '). + '
'; + } + $output .= &Apache::lonhtmlcommon::row_closure(1); + } + } + $output .= &Apache::lonhtmlcommon::end_pick_box(). + '
' + .''; + $r->print($output); + return; +} + +sub visible_in_cat { + my ($cdom,$cnum) = @_; + my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom); + my ($cathash,%settable,@vismsgs,$cansetvis); + my %visactions = &Apache::lonlocal::texthash( + vis => 'Your course/community currently appears in the Course/Community Catalog for this domain.', + gen => 'Courses can be both self-cataloging, based on an institutional code (e.g., fs08phy231), or can be assigned categories from a hierarchy defined for the domain.', + miss => 'Your course/community does not currently appear in the Course/Community Catalog for this domain.', + yous => 'You should remedy this if you plan to allow self-enrollment, otherwise students will have difficulty finding your course.', + coca => 'Courses can be absent from the Catalog, because they do not have an institutional code, have no assigned category, or have been specifically excluded.', + make => 'Make any changes to self-enrollment settings below, click "Save", then take action to include the course in the Catalog:', + take => 'Take the following action to ensure the course appears in the Catalog:', + dc_unhide => 'Ask a domain coordinator to change the "Exclude from course catalog" setting.', + dc_addinst => 'Ask a domain coordinator to enable display the catalog of "Official courses (with institutional codes)".', + dc_instcode => 'Ask a domain coordinator to assign an institutional code (if this is an official course).', + dc_catalog => 'Ask a domain coordinator to enable or create at least one course category in the domain.', + dc_categories => 'Ask a domain coordinator to create a hierarchy of categories and sub categories for courses in the domain.', + dc_chgcat => 'Ask a domain coordinator to change the category assigned to the course, as the one currently assigned is no longer used in the domain', + dc_addcat => 'Ask a domain coordinator to assign a category to the course.', + ); + $visactions{'unhide'} = &mt('Use [_1]Categorize course[_2] to change the "Exclude from course catalog" setting.','','"'); + $visactions{'chgcat'} = &mt('Use [_1]Categorize course[_2] to change the category assigned to the course, as the one currently assigned is no longer used in the domain.','"','"'); + $visactions{'addcat'} = &mt('Use [_1]Categorize course[_2] to assign a category to the course.','"','"'); + if (ref($domconf{'coursecategories'}) eq 'HASH') { + if ($domconf{'coursecategories'}{'togglecats'} eq 'crs') { + $settable{'togglecats'} = 1; + } + if ($domconf{'coursecategories'}{'categorize'} eq 'crs') { + $settable{'categorize'} = 1; + } + $cathash = $domconf{'coursecategories'}{'cats'}; + } + if ($settable{'togglecats'} && $settable{'categorize'}) { + $cansetvis = &mt('You are able to both assign a course category and choose to exclude this course from the catalog.'); + } elsif ($settable{'togglecats'}) { + $cansetvis = &mt('You are able to choose to exclude this course from the catalog, but only a Domain Coordinator may assign a course category.'); + } elsif ($settable{'categorize'}) { + $cansetvis = &mt('You may assign a course category, but only a Domain Coordinator may choose to exclude this course from the catalog.'); + } else { + $cansetvis = &mt('Only a Domain Coordinator may assign a course category or choose to exclude this course from the catalog.'); + } + + my %currsettings = + &Apache::lonnet::get('environment',['hidefromcat','categories','internal.coursecode'], + $cdom,$cnum); + my $visible = 0; + if ($currsettings{'internal.coursecode'} ne '') { + if (ref($domconf{'coursecategories'}) eq 'HASH') { + $cathash = $domconf{'coursecategories'}{'cats'}; + if (ref($cathash) eq 'HASH') { + if ($cathash->{'instcode::0'} eq '') { + push(@vismsgs,'dc_addinst'); + } else { + $visible = 1; + } + } else { + $visible = 1; + } + } else { + $visible = 1; + } + } else { + if (ref($cathash) eq 'HASH') { + if ($cathash->{'instcode::0'} ne '') { + push(@vismsgs,'dc_instcode'); + } + } else { + push(@vismsgs,'dc_instcode'); + } + } + if ($currsettings{'categories'} ne '') { + my $cathash; + if (ref($domconf{'coursecategories'}) eq 'HASH') { + $cathash = $domconf{'coursecategories'}{'cats'}; + if (ref($cathash) eq 'HASH') { + if (keys(%{$cathash}) == 0) { + push(@vismsgs,'dc_catalog'); + } elsif ((keys(%{$cathash}) == 1) && ($cathash->{'instcode::0'} ne '')) { + push(@vismsgs,'dc_categories'); + } else { + my @currcategories = split('&',$currsettings{'categories'}); + my $matched = 0; + foreach my $cat (@currcategories) { + if ($cathash->{$cat} ne '') { + $visible = 1; + $matched = 1; + last; + } + } + if (!$matched) { + if ($settable{'categorize'}) { + push(@vismsgs,'chgcat'); + } else { + push(@vismsgs,'dc_chgcat'); + } + } + } + } + } + } else { + if (ref($cathash) eq 'HASH') { + if ((keys(%{$cathash}) > 1) || + (keys(%{$cathash}) == 1) && ($cathash->{'instcode::0'} eq '')) { + if ($settable{'categorize'}) { + push(@vismsgs,'addcat'); + } else { + push(@vismsgs,'dc_addcat'); + } + } + } + } + if ($currsettings{'hidefromcat'} eq 'yes') { + $visible = 0; + if ($settable{'togglecats'}) { + unshift(@vismsgs,'unhide'); + } else { + unshift(@vismsgs,'dc_unhide') + } + } + return ($visible,$cansetvis,\@vismsgs,\%visactions); +} + +sub new_selfenroll_dom_row { + my ($newdom,$num) = @_; + my $domdesc = &Apache::lonnet::domain($newdom); + my $output; + if ($domdesc ne '') { + $output .= &Apache::loncommon::start_data_table_row() + .''.&mt('Domain:').' '.$domdesc + .' ('.$newdom.')
' + .''; + my @currinsttypes; + $output .= ''.&mt('User types:').'
' + .&selfenroll_inst_types($num,$newdom,\@currinsttypes).'' + .&Apache::loncommon::end_data_table_row(); + } + return $output; +} + +sub selfenroll_inst_types { + my ($num,$currdom,$currinsttypes) = @_; + my $output; + my $numinrow = 4; + my $count = 0; + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($currdom); + my $othervalue = 'any'; + if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) { + if (keys(%{$usertypes}) > 0) { + $othervalue = 'other'; + } + $output .= ''; + foreach my $type (@{$types}) { + if (($count > 0) && ($count%$numinrow == 0)) { + $output .= ''; + } + if (defined($usertypes->{$type})) { + my $esc_type = &escape($type); + $output .= ''; + } + $count ++; + } + if (($count > 0) && ($count%$numinrow == 0)) { + $output .= ''; + } + $output .= '
'; + } + return $output; +} + +sub selfenroll_date_forms { + my ($startform,$endform) = @_; + my $output .= &Apache::lonhtmlcommon::start_pick_box()."\n". + &Apache::lonhtmlcommon::row_title(&mt('Start date'), + 'LC_oddrow_value')."\n". + $startform."\n". + &Apache::lonhtmlcommon::row_closure(1). + &Apache::lonhtmlcommon::row_title(&mt('End date'), + 'LC_oddrow_value')."\n". + $endform."\n". + &Apache::lonhtmlcommon::row_closure(1). + &Apache::lonhtmlcommon::end_pick_box(); + return $output; +} + +sub print_userchangelogs_display { + my ($r,$context,$permission) = @_; + my $formname = 'roleslog'; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $crstype = &Apache::loncommon::course_type(); + my %roleslog=&Apache::lonnet::dump('nohist_rolelog',$cdom,$cnum); + if ((keys(%roleslog))[0]=~/^error\:/) { undef(%roleslog); } + + my %saveable_parameters = ('show' => 'scalar',); + &Apache::loncommon::store_course_settings('roles_log', + \%saveable_parameters); + &Apache::loncommon::restore_course_settings('roles_log', + \%saveable_parameters); + # set defaults + my $now = time(); + my $defstart = $now - (7*24*3600); #7 days ago + my %defaults = ( + page => '1', + show => '10', + role => 'any', + chgcontext => 'any', + rolelog_start_date => $defstart, + rolelog_end_date => $now, + ); + my $more_records = 0; + + # set current + my %curr; + foreach my $item ('show','page','role','chgcontext') { + $curr{$item} = $env{'form.'.$item}; + } + my ($startdate,$enddate) = + &Apache::lonuserutils::get_dates_from_form('rolelog_start_date','rolelog_end_date'); + $curr{'rolelog_start_date'} = $startdate; + $curr{'rolelog_end_date'} = $enddate; + foreach my $key (keys(%defaults)) { + if ($curr{$key} eq '') { + $curr{$key} = $defaults{$key}; + } + } + my (%whodunit,%changed,$version); + ($version) = ($r->dir_config('lonVersion') =~ /^([\d\.]+)\-/); + my ($minshown,$maxshown); + $minshown = 1; + my $count = 0; + if ($curr{'show'} ne &mt('all')) { + $maxshown = $curr{'page'} * $curr{'show'}; + if ($curr{'page'} > 1) { + $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'}; + } + } + + # Form Header + $r->print('
'. + &role_display_filter($formname,$cdom,$cnum,\%curr,$version,$crstype)); + + # Create navigation + my ($nav_script,$nav_links) = &userlogdisplay_nav($formname,\%curr,$more_records); + my $showntableheader = 0; + + # Table Header + my $tableheader = + &Apache::loncommon::start_data_table_header_row() + .' ' + .''.&mt('When').'' + .''.&mt('Who made the change').'' + .''.&mt('Changed User').'' + .''.&mt('Role').'' + .''.&mt('Section').'' + .''.&mt('Context').'' + .''.&mt('Start').'' + .''.&mt('End').'' + .&Apache::loncommon::end_data_table_header_row(); + + # Display user change log data + 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 ($count >= $curr{'page'} * $curr{'show'}) { + $more_records = 1; + last; + } + } + if ($curr{'role'} ne 'any') { + next if ($roleslog{$id}{'logentry'}{'role'} ne $curr{'role'}); + } + if ($curr{'chgcontext'} ne 'any') { + if ($curr{'chgcontext'} eq 'selfenroll') { + next if (!$roleslog{$id}{'logentry'}{'selfenroll'}); + } else { + next if ($roleslog{$id}{'logentry'}{'context'} ne $curr{'chgcontext'}); + } + } + $count ++; + next if ($count < $minshown); + unless ($showntableheader) { + $r->print($nav_script + .$nav_links + .&Apache::loncommon::start_data_table() + .$tableheader); + $r->rflush(); + $showntableheader = 1; + } + if ($whodunit{$roleslog{$id}{'exe_uname'}.':'.$roleslog{$id}{'exe_udom'}} eq '') { + $whodunit{$roleslog{$id}{'exe_uname'}.':'.$roleslog{$id}{'exe_udom'}} = + &Apache::loncommon::plainname($roleslog{$id}{'exe_uname'},$roleslog{$id}{'exe_udom'}); + } + if ($changed{$roleslog{$id}{'uname'}.':'.$roleslog{$id}{'udom'}} eq '') { + $changed{$roleslog{$id}{'uname'}.':'.$roleslog{$id}{'udom'}} = + &Apache::loncommon::plainname($roleslog{$id}{'uname'},$roleslog{$id}{'udom'}); + } + my $sec = $roleslog{$id}{'logentry'}{'section'}; + if ($sec eq '') { + $sec = &mt('None'); + } + my ($rolestart,$roleend); + if ($roleslog{$id}{'delflag'}) { + $rolestart = &mt('deleted'); + $roleend = &mt('deleted'); + } else { + $rolestart = $roleslog{$id}{'logentry'}{'start'}; + $roleend = $roleslog{$id}{'logentry'}{'end'}; + if ($rolestart eq '' || $rolestart == 0) { + $rolestart = &mt('No start date'); + } else { + $rolestart = &Apache::lonlocal::locallocaltime($rolestart); + } + if ($roleend eq '' || $roleend == 0) { + $roleend = &mt('No end date'); + } else { + $roleend = &Apache::lonlocal::locallocaltime($roleend); + } + } + my $chgcontext = $roleslog{$id}{'logentry'}{'context'}; + if ($roleslog{$id}{'logentry'}{'selfenroll'}) { + $chgcontext = 'selfenroll'; + } + my %lt = &rolechg_contexts($crstype); + if ($chgcontext ne '' && $lt{$chgcontext} ne '') { + $chgcontext = $lt{$chgcontext}; + } + $r->print( + &Apache::loncommon::start_data_table_row() + .''.$count.'' + .''.&Apache::lonlocal::locallocaltime($roleslog{$id}{'exe_time'}).'' + .''.$whodunit{$roleslog{$id}{'exe_uname'}.':'.$roleslog{$id}{'exe_udom'}}.'' + .''.$changed{$roleslog{$id}{'uname'}.':'.$roleslog{$id}{'udom'}}.'' + .''.&Apache::lonnet::plaintext($roleslog{$id}{'logentry'}{'role'},$crstype).'' + .''.$sec.'' + .''.$chgcontext.'' + .''.$rolestart.'' + .''.$roleend.'' + .&Apache::loncommon::end_data_table_row()."\n"); + } + + if ($showntableheader) { # Table footer, if content displayed above + $r->print(&Apache::loncommon::end_data_table() + .$nav_links); + } else { # No content displayed above + $r->print('

' + .&mt('There are no records to display.') + .'

' + ); + } + + # Form Footer + $r->print( + '' + .'' + .'
'); + 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"; + +ENDSCRIPT + # Navigation Buttons + $nav_links = '

'; + if (($curr->{'page'} > 1) || ($more_records)) { + if ($curr->{'page'} > 1) { + $nav_links .= ' '; + } + if ($more_records) { + $nav_links .= ''; + } + } + $nav_links .= '

'; + } + return ($nav_script,$nav_links); +} + +sub role_display_filter { + my ($formname,$cdom,$cnum,$curr,$version,$crstype) = @_; + my $context = 'course'; + my $lctype = lc($crstype); + my $nolink = 1; + my $output = ''; + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'rolelog_start_date', + $curr->{'rolelog_start_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'rolelog_end_date', + $curr->{'rolelog_end_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + my %lt = &rolechg_contexts($crstype); + $output .= ''. + ''. + ''. + ''. + '' + .'
'. + ''.&mt('Changes/page:').'
'. + &Apache::lonmeta::selectbox('show',$curr->{'show'},undef, + (&mt('all'),5,10,20,50,100,1000,10000)). + '
  '.&mt('Window during which changes occurred:').'
'. + ''. + ''. + '
'.&mt('After:'). + ''.$startform.'
'.&mt('Before:').''.$endform.'
'. + '
  '.&mt('Role:').'
'. + '
  '. + &mt('Context:').'
'; + + # Update Display button + $output .= '

' + .'' + .'

'; + + # Server version info + $output .= '

' + .&mt('Only changes made from servers running LON-CAPA [_1] or later are displayed.' + ,'2.6.99.0'); + if ($version) { + $output .= ' '.&mt('This LON-CAPA server is version [_1]',$version); + } + $output .= '


'; + return $output; +} + +sub rolechg_contexts { + my ($crstype) = @_; + my %lt = &Apache::lonlocal::texthash ( + any => 'Any', + auto => 'Automated enrollment', + updatenow => 'Roster Update', + createcourse => 'Course Creation', + course => 'User Management in course', + domain => 'User Management in domain', + selfenroll => 'Self-enrolled', + requestcourses => 'Course Request', + ); + if ($crstype eq 'Community') { + $lt{'createcourse'} = &mt('Community Creation'); + $lt{'course'} = &mt('User Management in community'); + $lt{'requestcourses'} = &mt('Community Request'); + } + return %lt; +} #-------------------------------------------------- functions for &phase_two +sub user_search_result { + my ($context,$srch) = @_; + my %allhomes; + my %inst_matches; + my %srch_results; + my ($response,$currstate,$forcenewuser,$dirsrchres); + $srch->{'srchterm'} =~ s/\s+/ /g; + if ($srch->{'srchby'} !~ /^(uname|lastname|lastfirst)$/) { + $response = &mt('Invalid search.'); + } + if ($srch->{'srchin'} !~ /^(crs|dom|alc|instd)$/) { + $response = &mt('Invalid search.'); + } + if ($srch->{'srchtype'} !~ /^(exact|contains|begins)$/) { + $response = &mt('Invalid search.'); + } + if ($srch->{'srchterm'} eq '') { + $response = &mt('You must enter a search term.'); + } + if ($srch->{'srchterm'} =~ /^\s+$/) { + $response = &mt('Your search term must contain more than just spaces.'); + } + if (($srch->{'srchin'} eq 'dom') || ($srch->{'srchin'} eq 'instd')) { + if (($srch->{'srchdomain'} eq '') || + ! (&Apache::lonnet::domain($srch->{'srchdomain'}))) { + $response = &mt('You must specify a valid domain when searching in a domain or institutional directory.') + } + } + if (($srch->{'srchin'} eq 'dom') || ($srch->{'srchin'} eq 'crs') || + ($srch->{'srchin'} eq 'alc')) { + if ($srch->{'srchby'} eq 'uname') { + my $unamecheck = $srch->{'srchterm'}; + if ($srch->{'srchtype'} eq 'contains') { + if ($unamecheck !~ /^\w/) { + $unamecheck = 'a'.$unamecheck; + } + } + if ($unamecheck !~ /^$match_username$/) { + $response = &mt('You must specify a valid username. Only the following are allowed: letters numbers - . @'); + } + } + } + if ($response ne '') { + $response = ''.$response.''; + } + if ($srch->{'srchin'} eq 'instd') { + my $instd_chk = &directorysrch_check($srch); + if ($instd_chk ne 'ok') { + $response = ''.$instd_chk.''. + '
'.&mt('You may want to search in the LON-CAPA domain instead of the institutional directory.').'

'; + } + } + if ($response ne '') { + return ($currstate,$response); + } + if ($srch->{'srchby'} eq 'uname') { + if (($srch->{'srchin'} eq 'dom') || ($srch->{'srchin'} eq 'crs')) { + if ($env{'form.forcenew'}) { + if ($srch->{'srchdomain'} ne $env{'request.role.domain'}) { + my $uhome=&Apache::lonnet::homeserver($srch->{'srchterm'},$srch->{'srchdomain'}); + if ($uhome eq 'no_host') { + my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description'); + my $showdom = &display_domain_info($env{'request.role.domain'}); + $response = &mt('New users can only be created in the domain to which your current role belongs - [_1].',$showdom); + } else { + $currstate = 'modify'; + } + } else { + $currstate = 'modify'; + } + } else { + if ($srch->{'srchin'} eq 'dom') { + if ($srch->{'srchtype'} eq 'exact') { + my $uhome=&Apache::lonnet::homeserver($srch->{'srchterm'},$srch->{'srchdomain'}); + if ($uhome eq 'no_host') { + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } else { + $currstate = 'modify'; + my $uname = $srch->{'srchterm'}; + my $udom = $srch->{'srchdomain'}; + $srch_results{$uname.':'.$udom} = + { &Apache::lonnet::get('environment', + ['firstname', + 'lastname', + 'permanentemail'], + $udom,$uname) + }; + } + } else { + %srch_results = &Apache::lonnet::usersearch($srch); + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } + } else { + my $courseusers = &get_courseusers(); + if ($srch->{'srchtype'} eq 'exact') { + if (exists($courseusers->{$srch->{'srchterm'}.':'.$srch->{'srchdomain'}})) { + $currstate = 'modify'; + } else { + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } + } else { + foreach my $user (keys(%$courseusers)) { + my ($cuname,$cudomain) = split(/:/,$user); + if ($cudomain eq $srch->{'srchdomain'}) { + my $matched = 0; + if ($srch->{'srchtype'} eq 'begins') { + if ($cuname =~ /^\Q$srch->{'srchterm'}\E/i) { + $matched = 1; + } + } else { + if ($cuname =~ /\Q$srch->{'srchterm'}\E/i) { + $matched = 1; + } + } + if ($matched) { + $srch_results{$user} = + {&Apache::lonnet::get('environment', + ['firstname', + 'lastname', + 'permanentemail'], + $cudomain,$cuname)}; + } + } + } + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } + } + } + } elsif ($srch->{'srchin'} eq 'alc') { + $currstate = 'query'; + } elsif ($srch->{'srchin'} eq 'instd') { + ($dirsrchres,%srch_results) = &Apache::lonnet::inst_directory_query($srch); + if ($dirsrchres eq 'ok') { + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } else { + my $showdom = &display_domain_info($srch->{'srchdomain'}); + $response = ''. + &mt('Institutional directory search is not available in domain: [_1]',$showdom). + '
'. + &mt('You may want to search in the LON-CAPA domain instead of the institutional directory.'). + '

'; + } + } + } else { + if ($srch->{'srchin'} eq 'dom') { + %srch_results = &Apache::lonnet::usersearch($srch); + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } elsif ($srch->{'srchin'} eq 'crs') { + my $courseusers = &get_courseusers(); + foreach my $user (keys(%$courseusers)) { + my ($uname,$udom) = split(/:/,$user); + my %names = &Apache::loncommon::getnames($uname,$udom); + my %emails = &Apache::loncommon::getemails($uname,$udom); + if ($srch->{'srchby'} eq 'lastname') { + if ((($srch->{'srchtype'} eq 'exact') && + ($names{'lastname'} eq $srch->{'srchterm'})) || + (($srch->{'srchtype'} eq 'begins') && + ($names{'lastname'} =~ /^\Q$srch->{'srchterm'}\E/i)) || + (($srch->{'srchtype'} eq 'contains') && + ($names{'lastname'} =~ /\Q$srch->{'srchterm'}\E/i))) { + $srch_results{$user} = {firstname => $names{'firstname'}, + lastname => $names{'lastname'}, + permanentemail => $emails{'permanentemail'}, + }; + } + } elsif ($srch->{'srchby'} eq 'lastfirst') { + my ($srchlast,$srchfirst) = split(/,/,$srch->{'srchterm'}); + $srchlast =~ s/\s+$//; + $srchfirst =~ s/^\s+//; + if ($srch->{'srchtype'} eq 'exact') { + if (($names{'lastname'} eq $srchlast) && + ($names{'firstname'} eq $srchfirst)) { + $srch_results{$user} = {firstname => $names{'firstname'}, + lastname => $names{'lastname'}, + permanentemail => $emails{'permanentemail'}, + + }; + } + } elsif ($srch->{'srchtype'} eq 'begins') { + if (($names{'lastname'} =~ /^\Q$srchlast\E/i) && + ($names{'firstname'} =~ /^\Q$srchfirst\E/i)) { + $srch_results{$user} = {firstname => $names{'firstname'}, + lastname => $names{'lastname'}, + permanentemail => $emails{'permanentemail'}, + }; + } + } else { + if (($names{'lastname'} =~ /\Q$srchlast\E/i) && + ($names{'firstname'} =~ /\Q$srchfirst\E/i)) { + $srch_results{$user} = {firstname => $names{'firstname'}, + lastname => $names{'lastname'}, + permanentemail => $emails{'permanentemail'}, + }; + } + } + } + } + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } elsif ($srch->{'srchin'} eq 'alc') { + $currstate = 'query'; + } elsif ($srch->{'srchin'} eq 'instd') { + ($dirsrchres,%srch_results) = &Apache::lonnet::inst_directory_query($srch); + if ($dirsrchres eq 'ok') { + ($currstate,$response,$forcenewuser) = + &build_search_response($context,$srch,%srch_results); + } else { + my $showdom = &display_domain_info($srch->{'srchdomain'}); $response = ''. + &mt('Institutional directory search is not available in domain: [_1]',$showdom). + '
'. + &mt('You may want to search in the LON-CAPA domain instead of the institutional directory.'). + '

'; + } + } + } + return ($currstate,$response,$forcenewuser,\%srch_results); +} + +sub directorysrch_check { + my ($srch) = @_; + my $can_search = 0; + my $response; + my %dom_inst_srch = &Apache::lonnet::get_dom('configuration', + ['directorysrch'],$srch->{'srchdomain'}); + my $showdom = &display_domain_info($srch->{'srchdomain'}); + if (ref($dom_inst_srch{'directorysrch'}) eq 'HASH') { + if (!$dom_inst_srch{'directorysrch'}{'available'}) { + return &mt('Institutional directory search is not available in domain: [_1]',$showdom); + } + if ($dom_inst_srch{'directorysrch'}{'localonly'}) { + if ($env{'request.role.domain'} ne $srch->{'srchdomain'}) { + return &mt('Institutional directory search in domain: [_1] is only allowed for users with a current role in the domain.',$showdom); + } + my @usertypes = split(/:/,$env{'environment.inststatus'}); + if (!@usertypes) { + push(@usertypes,'default'); + } + if (ref($dom_inst_srch{'directorysrch'}{'cansearch'}) eq 'ARRAY') { + foreach my $type (@usertypes) { + if (grep(/^\Q$type\E$/,@{$dom_inst_srch{'directorysrch'}{'cansearch'}})) { + $can_search = 1; + last; + } + } + } + if (!$can_search) { + my ($insttypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($srch->{'srchdomain'}); + my @longtypes; + foreach my $item (@usertypes) { + if (defined($insttypes->{$item})) { + push (@longtypes,$insttypes->{$item}); + } elsif ($item eq 'default') { + push (@longtypes,&mt('other')); + } + } + my $insttype_str = join(', ',@longtypes); + return &mt('Institutional directory search in domain: [_1] is not available to your user type: ',$showdom).$insttype_str; + } + } else { + $can_search = 1; + } + } else { + return &mt('Institutional directory search has not been configured for domain: [_1]',$showdom); + } + my %longtext = &Apache::lonlocal::texthash ( + uname => 'username', + lastfirst => 'last name, first name', + lastname => 'last name', + contains => 'contains', + exact => 'as exact match to', + begins => 'begins with', + ); + if ($can_search) { + if (ref($dom_inst_srch{'directorysrch'}{'searchby'}) eq 'ARRAY') { + if (!grep(/^\Q$srch->{'srchby'}\E$/,@{$dom_inst_srch{'directorysrch'}{'searchby'}})) { + return &mt('Institutional directory search in domain: [_1] is not available for searching by "[_2]"',$showdom,$longtext{$srch->{'srchby'}}); + } + } else { + return &mt('Institutional directory search in domain: [_1] is not available.', $showdom); + } + } + if ($can_search) { + if (ref($dom_inst_srch{'directorysrch'}{'searchtypes'}) eq 'ARRAY') { + if (grep(/^\Q$srch->{'srchtype'}\E/,@{$dom_inst_srch{'directorysrch'}{'searchtypes'}})) { + return 'ok'; + } else { + return &mt('Institutional directory search in domain [_1] is not available for the requested search type: "[_2]"',$showdom,$longtext{$srch->{'srchtype'}}); + } + } else { + if ((($dom_inst_srch{'directorysrch'}{'searchtypes'} eq 'specify') && + ($srch->{'srchtype'} eq 'exact' || $srch->{'srchtype'} eq 'contains')) || + ($dom_inst_srch{'directorysrch'}{'searchtypes'} eq $srch->{'srchtype'})) { + return 'ok'; + } else { + return &mt('Institutional directory search in domain [_1] is not available for the requested search type: "[_2]"',$showdom,$longtext{$srch->{'srchtype'}}); + } + } + } +} + +sub get_courseusers { + my %advhash; + my $classlist = &Apache::loncoursedata::get_classlist(); + my %coursepersonnel=&Apache::lonnet::get_course_adv_roles(); + foreach my $role (sort(keys(%coursepersonnel))) { + foreach my $user (split(/\,/,$coursepersonnel{$role})) { + if (!exists($classlist->{$user})) { + $classlist->{$user} = []; + } + } + } + return $classlist; +} + +sub build_search_response { + my ($context,$srch,%srch_results) = @_; + my ($currstate,$response,$forcenewuser); + my %names = ( + 'uname' => 'username', + 'lastname' => 'last name', + 'lastfirst' => 'last name, first name', + 'crs' => 'this course', + 'dom' => 'LON-CAPA domain', + 'instd' => 'the institutional directory for domain', + ); + + my %single = ( + begins => 'A match', + contains => 'A match', + exact => 'An exact match', + ); + my %nomatch = ( + begins => 'No match', + contains => 'No match', + exact => 'No exact match', + ); + if (keys(%srch_results) > 1) { + $currstate = 'select'; + } else { + if (keys(%srch_results) == 1) { + $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'}); + } + } else { # Search has nothing found. Prepare message to user. + $response = ''; + if ($srch->{'srchin'} eq 'dom' || $srch->{'srchin'} eq 'instd') { + $response .= &mt("$nomatch{$srch->{'srchtype'}} found for the $names{$srch->{'srchby'}} [_1] in $names{$srch->{'srchin'}}: [_2]", + ''.$srch->{'srchterm'}.'', + &display_domain_info($srch->{'srchdomain'})); + } else { + $response .= &mt("$nomatch{$srch->{'srchtype'}} found for the $names{$srch->{'srchby'}} [_1] in $names{$srch->{'srchin'}}.", + ''.$srch->{'srchterm'}.''); + } + $response .= ''; + + if ($srch->{'srchin'} ne 'alc') { + $forcenewuser = 1; + my $cansrchinst = 0; + if ($srch->{'srchdomain'}) { + my %domconfig = &Apache::lonnet::get_dom('configuration',['directorysrch'],$srch->{'srchdomain'}); + if (ref($domconfig{'directorysrch'}) eq 'HASH') { + if ($domconfig{'directorysrch'}{'available'}) { + $cansrchinst = 1; + } + } + } + if ((($srch->{'srchby'} eq 'lastfirst') || + ($srch->{'srchby'} eq 'lastname')) && + ($srch->{'srchin'} eq 'dom')) { + if ($cansrchinst) { + $response .= '
'.&mt('You may want to broaden your search to a search of the institutional directory for the domain.'); + } + } + if ($srch->{'srchin'} eq 'crs') { + $response .= '
'.&mt('You may want to broaden your search to the selected LON-CAPA domain.'); + } + } + my $createdom = $env{'request.role.domain'}; + if ($context eq 'requestcrs') { + if ($env{'form.coursedom'} ne '') { + $createdom = $env{'form.coursedom'}; + } + } + if (!($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 = ''.$createdom.''; + if ($cancreate) { + my $showdom = &display_domain_info($createdom); + $response .= '

' + .''.&mt('To add a new user:').'' + .'
'; + if ($context eq 'requestcrs') { + $response .= &mt("(You can only define new users in the new course's domain - [_1])",$targetdom); + } else { + $response .= &mt("(You can only create new users in your current role's domain - [_1])",$targetdom); + } + $response .='
  • ' + .&mt("Set 'Domain/institution to search' to: [_1]",''.$showdom.'') + .'
  • ' + .&mt("Set 'Search criteria' to: [_1]username is ..... in selected LON-CAPA domain[_2]",'','') + .'
  • ' + .&mt('Provide the proposed username') + .'
  • ' + .&mt("Click 'Search'") + .'

'; + } else { + my $helplink = ' href="javascript:helpMenu('."'display'".')"'; + $response .= '

'; + if ($context eq 'requestcrs') { + $response .= &mt("You are not authorized to define new users in the new course's domain - [_1].",$targetdom); + } else { + $response .= &mt("You are not authorized to create new users in your current role's domain - [_1].",$targetdom); + } + $response .= '
' + .&mt('Please contact the [_1]helpdesk[_2] if you need to create a new user.' + ,' ' + ,'') + .'

'; + } + } + } + } + return ($currstate,$response,$forcenewuser); +} + +sub display_domain_info { + my ($dom) = @_; + my $output = $dom; + if ($dom ne '') { + my $domdesc = &Apache::lonnet::domain($dom,'description'); + if ($domdesc ne '') { + $output .= ' ('.$domdesc.')'; + } + } + return $output; +} + +sub crumb_utilities { + my %elements = ( + crtuser => { + srchterm => 'text', + srchin => 'selectbox', + srchby => 'selectbox', + srchtype => 'selectbox', + srchdomain => 'selectbox', + }, + crtusername => { + srchterm => 'text', + srchdomain => 'selectbox', + }, + docustom => { + rolename => 'selectbox', + newrolename => 'textbox', + }, + studentform => { + srchterm => 'text', + srchin => 'selectbox', + srchby => 'selectbox', + srchtype => 'selectbox', + srchdomain => 'selectbox', + }, + ); + + my $jsback .= qq| +function backPage(formname,prevphase,prevstate) { + if (typeof prevphase == 'undefined') { + formname.phase.value = ''; + } + else { + formname.phase.value = prevphase; + } + if (typeof prevstate == 'undefined') { + formname.currstate.value = ''; + } + else { + formname.currstate.value = prevstate; + } + formname.submit(); +} +|; + return ($jsback,\%elements); +} + sub course_level_table { my (%inccourses) = @_; my $table = ''; # Custom Roles? - my %customroles=&my_custom_roles(); + my %customroles=&Apache::lonuserutils::my_custom_roles(); my %lt=&Apache::lonlocal::texthash( 'exs' => "Existing sections", 'new' => "Define new section", @@ -1748,12 +6095,13 @@ sub course_level_table { 'end' => "End" ); - foreach my $protectedcourse (sort( keys(%inccourses))) { + foreach my $protectedcourse (sort(keys(%inccourses))) { my $thiscourse=$protectedcourse; $thiscourse=~s:_:/:g; my %coursedata=&Apache::lonnet::coursedescription($thiscourse); + my $isowner = &is_courseowner($protectedcourse,$coursedata{'internal.courseowner'}); my $area=$coursedata{'description'}; - my $type=$coursedata{'type'}; + my $crstype=$coursedata{'type'}; if (!defined($area)) { $area=&mt('Unavailable course').': '.$protectedcourse; } my ($domain,$cnum)=split(/\//,$thiscourse); my %sections_count; @@ -1763,131 +6111,105 @@ sub course_level_table { &Apache::loncommon::get_sections($domain,$cnum); } } - foreach my $role ('st','ta','ep','in','cc') { - if (&Apache::lonnet::allowed('c'.$role,$thiscourse)) { - my $plrole=&Apache::lonnet::plaintext($role); - $table .= &Apache::loncommon::start_data_table_row(). -' -'.$plrole.' -'.$area.'
Domain: '.$domain.''."\n"; - if ($role ne 'cc') { - if (%sections_count) { - my $currsec = &course_sections(\%sections_count,$protectedcourse.'_'.$role); - $table .= - ''. - ' - '. - ''. - ''. - ''. - '
'.$lt{'exs'}.'
'. - $currsec.'
   '.$lt{'new'}.'
'. - '
'; - } else { - $table .= ''; - } - } else { - $table .= ' '; + my @roles = &Apache::lonuserutils::roles_by_context('course','',$crstype); + foreach my $role (@roles) { + my $plrole=&Apache::lonnet::plaintext($role,$crstype); + if ((&Apache::lonnet::allowed('c'.$role,$thiscourse)) || + ((($role eq 'cc') || ($role eq 'co')) && ($isowner))) { + $table .= &course_level_row($protectedcourse,$role,$area,$domain, + $plrole,\%sections_count,\%lt); + } elsif ($env{'request.course.sec'} ne '') { + if (&Apache::lonnet::allowed('c'.$role,$thiscourse.'/'. + $env{'request.course.sec'})) { + $table .= &course_level_row($protectedcourse,$role,$area,$domain, + $plrole,\%sections_count,\%lt); } - $table .= < -$lt{'ssd'} - -$lt{'sed'} -ENDTIMEENTRY - $table.= &Apache::loncommon::end_data_table_row(); } } - foreach my $cust (sort keys %customroles) { - if (&Apache::lonnet::allowed('ccr',$thiscourse)) { - my $plrole=$cust; - my $customrole=$protectedcourse.'_cr_cr_'.$env{'user.domain'}. - '_'.$env{'user.name'}.'_'.$plrole; - $table .= &Apache::loncommon::start_data_table_row(). -' -'.$plrole.' -'.$area.''."\n"; - if (%sections_count) { - my $currsec = &course_sections(\%sections_count,$customrole); - $table.= - ''. - ''. - ''. - ''. - ''. - '
'.$lt{'exs'}.'
'. - $currsec.'
   '.$lt{'new'}.'
'. - '
'; - } else { - $table .= ''; - } - $table .= < -$lt{'ssd'} - -$lt{'sed'} -ENDENTRY - $table .= &Apache::loncommon::end_data_table_row(); - } + if (&Apache::lonnet::allowed('ccr',$thiscourse)) { + foreach my $cust (sort(keys(%customroles))) { + next if ($crstype eq 'Community' && $customroles{$cust} =~ /bre\&S/); + my $role = 'cr_cr_'.$env{'user.domain'}.'_'.$env{'user.name'}.'_'.$cust; + $table .= &course_level_row($protectedcourse,$role,$area,$domain, + $cust,\%sections_count,\%lt); + } } } return '' if ($table eq ''); # return nothing if there is nothing # in the table - my $result = ' -

'.$lt{'crl'}.'

'. + my $result; + if (!$env{'request.course.id'}) { + $result = '

'.$lt{'crl'}.'

'."\n"; + } + $result .= &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). ''.$lt{'act'}.''.$lt{'rol'}.''.$lt{'ext'}.' '.$lt{'grs'}.''.$lt{'sta'}.''.$lt{'end'}.''. &Apache::loncommon::end_data_table_header_row(). -&Apache::loncommon::start_data_table_row(). $table. -&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); return $result; } -sub course_sections { - my ($sections_count,$role) = @_; - my $output = ''; - my @sections = (sort {$a <=> $b} keys %{$sections_count}); - if (scalar(@sections) == 1) { - $output = ''."\n"; - foreach my $sec (@sections) { - $output .= '\n"; +sub course_level_row { + my ($protectedcourse,$role,$area,$domain,$plrole,$sections_count,$lt) = @_; + my $row = &Apache::loncommon::start_data_table_row(). + ' '."\n". + ' '.$plrole.''."\n". + ' '.$area.'
Domain: '.$domain.''."\n"; + if (($role eq 'cc') || ($role eq 'co')) { + $row .= ' '; + } elsif ($env{'request.course.sec'} ne '') { + $row .= ' '. + $env{'request.course.sec'}.''; + } else { + if (ref($sections_count) eq 'HASH') { + my $currsec = + &Apache::lonuserutils::course_sections($sections_count, + $protectedcourse.'_'.$role); + $row .= ''."\n". + ''."\n". + ' '."\n". + ' '."\n". + ' '."\n". + '
'.$lt->{'exs'}.'
'. + $currsec.'
   '.$lt->{'new'}.'
'. + ''. + '
'."\n"; + } else { + $row .= ''."\n"; } } - $output .= ''; - return $output; + $row .= < +$lt->{'ssd'} + +$lt->{'sed'} +ENDTIMEENTRY + $row .= &Apache::loncommon::end_data_table_row(); + return $row; } sub course_level_dc { my ($dcdom) = @_; - my %customroles=&my_custom_roles(); + my %customroles=&Apache::lonuserutils::my_custom_roles(); + my @roles = &Apache::lonuserutils::roles_by_context('course'); my $hiddenitems = ''. ''. ''; my $courseform=''.&Apache::loncommon::selectcourse_link - ('cu','dccourse','dcdomain','coursedesc',undef,undef,'Course').''; - my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($dcdom,'currsec','cu'); + ('cu','dccourse','dcdomain','coursedesc',undef,undef,'Course/Community','crstype').'
'; + my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($dcdom,'currsec','cu','role','Course/Community Browser'); my %lt=&Apache::lonlocal::texthash( - 'typ' => "Type", 'rol' => "Role", 'grs' => "Section", 'exs' => "Existing sections", @@ -1897,20 +6219,15 @@ sub course_level_dc { 'ssd' => "Set Start Date", 'sed' => "Set End Date" ); - my $header = '

'.&mt('Course Level').'

'. + my $header = '

'.&mt('Course/Community Level').'

'. &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). - ''.$lt{'typ'}.''.$courseform.''.$lt{'rol'}.''.$lt{'grs'}.''.$lt{'sta'}.''.$lt{'end'}.''. + ''.$courseform.''.$lt{'rol'}.''.$lt{'grs'}.''.$lt{'sta'}.''.$lt{'end'}.''. &Apache::loncommon::end_data_table_header_row(); - my $otheritems = &Apache::loncommon::start_data_table_row(). - ''."\n". - ''."\n". - ''."\n". + '
'. - ''. + ''. + ''. + ''. ''; $otheritems .= < +
$lt{'ssd'} - +
$lt{'sed'} ENDTIMEENTRY @@ -1943,6 +6262,380 @@ ENDTIMEENTRY return $cb_jscript.$header.$hiddenitems.$otheritems; } +sub update_selfenroll_config { + my ($r,$context,$permission) = @_; + my ($row,$lt) = &get_selfenroll_titles(); + my %curr_groups = &Apache::longroup::coursegroups(); + my (%changes,%warning); + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $curr_types; + if (ref($row) eq 'ARRAY') { + foreach my $item (@{$row}) { + if ($item eq 'enroll_dates') { + my (%currenrolldate,%newenrolldate); + foreach my $type ('start','end') { + $currenrolldate{$type} = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_'.$type.'_date'}; + $newenrolldate{$type} = &Apache::lonhtmlcommon::get_date_from_form('selfenroll_'.$type.'_date'); + if ($newenrolldate{$type} ne $currenrolldate{$type}) { + $changes{'internal.selfenroll_'.$type.'_date'} = $newenrolldate{$type}; + } + } + } elsif ($item eq 'access_dates') { + my (%currdate,%newdate); + foreach my $type ('start','end') { + $currdate{$type} = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_'.$type.'_access'}; + $newdate{$type} = &Apache::lonhtmlcommon::get_date_from_form('selfenroll_'.$type.'_access'); + if ($newdate{$type} ne $currdate{$type}) { + $changes{'internal.selfenroll_'.$type.'_access'} = $newdate{$type}; + } + } + } elsif ($item eq 'types') { + $curr_types = + $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_'.$item}; + if ($env{'form.selfenroll_all'}) { + if ($curr_types ne '*') { + $changes{'internal.selfenroll_types'} = '*'; + } else { + next; + } + } else { + my %currdoms; + my @entries = split(/;/,$curr_types); + my @deletedoms = &Apache::loncommon::get_env_multiple('form.selfenroll_delete'); + my @activations = &Apache::loncommon::get_env_multiple('form.selfenroll_activate'); + my $newnum = 0; + my @latesttypes; + foreach my $num (@activations) { + my @types = &Apache::loncommon::get_env_multiple('form.selfenroll_types_'.$num); + if (@types > 0) { + @types = sort(@types); + my $typestr = join(',',@types); + my $typedom = $env{'form.selfenroll_dom_'.$num}; + $latesttypes[$newnum] = $typedom.':'.$typestr; + $currdoms{$typedom} = 1; + $newnum ++; + } + } + for (my $j=0; $j<$env{'form.selfenroll_types_total'}; $j++) { + if ((!grep(/^$j$/,@deletedoms)) && (!grep(/^$j$/,@activations))) { + my @types = &Apache::loncommon::get_env_multiple('form.selfenroll_types_'.$j); + if (@types > 0) { + @types = sort(@types); + my $typestr = join(',',@types); + my $typedom = $env{'form.selfenroll_dom_'.$j}; + $latesttypes[$newnum] = $typedom.':'.$typestr; + $currdoms{$typedom} = 1; + $newnum ++; + } + } + } + if ($env{'form.selfenroll_newdom'} ne '') { + my $typedom = $env{'form.selfenroll_newdom'}; + if ((!defined($currdoms{$typedom})) && + (&Apache::lonnet::domain($typedom) ne '')) { + my $typestr; + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($typedom); + my $othervalue = 'any'; + if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) { + if (@{$types} > 0) { + my @esc_types = map { &escape($_); } @{$types}; + $othervalue = 'other'; + $typestr = join(',',(@esc_types,$othervalue)); + } + $typestr = $othervalue; + } else { + $typestr = $othervalue; + } + $latesttypes[$newnum] = $typedom.':'.$typestr; + $newnum ++ ; + } + } + my $selfenroll_types = join(';',@latesttypes); + if ($selfenroll_types ne $curr_types) { + $changes{'internal.selfenroll_types'} = $selfenroll_types; + } + } + } elsif ($item eq 'limit') { + my $newlimit = $env{'form.selfenroll_limit'}; + my $newcap = $env{'form.selfenroll_cap'}; + $newcap =~s/\s+//g; + my $currlimit = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_limit'}; + $currlimit = 'none' if ($currlimit eq ''); + my $currcap = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_cap'}; + if ($newlimit ne $currlimit) { + if ($newlimit ne 'none') { + if ($newcap =~ /^\d+$/) { + if ($newcap ne $currcap) { + $changes{'internal.selfenroll_cap'} = $newcap; + } + $changes{'internal.selfenroll_limit'} = $newlimit; + } else { + $warning{$item} = &mt('Maximum enrollment setting unchanged.').'
'.&mt('The value provided was invalid - it must be a positive integer if enrollment is being limited.'); + } + } elsif ($currcap ne '') { + $changes{'internal.selfenroll_cap'} = ''; + $changes{'internal.selfenroll_limit'} = $newlimit; + } + } elsif ($currlimit ne 'none') { + if ($newcap =~ /^\d+$/) { + if ($newcap ne $currcap) { + $changes{'internal.selfenroll_cap'} = $newcap; + } + } else { + $warning{$item} = &mt('Maximum enrollment setting unchanged.').'
'.&mt('The value provided was invalid - it must be a positive integer if enrollment is being limited.'); + } + } + } elsif ($item eq 'approval') { + my (@currnotified,@newnotified); + my $currapproval = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_approval'}; + my $currnotifylist = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_notifylist'}; + if ($currnotifylist ne '') { + @currnotified = split(/,/,$currnotifylist); + @currnotified = sort(@currnotified); + } + my $newapproval = $env{'form.selfenroll_approval'}; + @newnotified = &Apache::loncommon::get_env_multiple('form.selfenroll_notify'); + @newnotified = sort(@newnotified); + if ($newapproval ne $currapproval) { + $changes{'internal.selfenroll_approval'} = $newapproval; + if (!$newapproval) { + if ($currnotifylist ne '') { + $changes{'internal.selfenroll_notifylist'} = ''; + } + } else { + my @differences = + &Apache::loncommon::compare_arrays(\@currnotified,\@newnotified); + if (@differences > 0) { + if (@newnotified > 0) { + $changes{'internal.selfenroll_notifylist'} = join(',',@newnotified); + } else { + $changes{'internal.selfenroll_notifylist'} = join(',',@newnotified); + } + } + } + } else { + my @differences = &Apache::loncommon::compare_arrays(\@currnotified,\@newnotified); + if (@differences > 0) { + if (@newnotified > 0) { + $changes{'internal.selfenroll_notifylist'} = join(',',@newnotified); + } else { + $changes{'internal.selfenroll_notifylist'} = ''; + } + } + } + } else { + my $curr_val = + $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_'.$item}; + my $newval = $env{'form.selfenroll_'.$item}; + if ($item eq 'section') { + $newval = $env{'form.sections'}; + if (defined($curr_groups{$newval})) { + $newval = $curr_val; + $warning{$item} = &mt('Section for self-enrolled users unchanged as the proposed section is a group').'
'.&mt('Group names and section names must be distinct'); + } elsif ($newval eq 'all') { + $newval = $curr_val; + $warning{$item} = &mt('Section for self-enrolled users unchanged, as "all" is a reserved section name.'); + } + if ($newval eq '') { + $newval = 'none'; + } + } + if ($newval ne $curr_val) { + $changes{'internal.selfenroll_'.$item} = $newval; + } + } + } + if (keys(%warning) > 0) { + foreach my $item (@{$row}) { + if (exists($warning{$item})) { + $r->print($warning{$item}.'
'); + } + } + } + if (keys(%changes) > 0) { + my $putresult = &Apache::lonnet::put('environment',\%changes,$cdom,$cnum); + if ($putresult eq 'ok') { + if ((exists($changes{'internal.selfenroll_types'})) || + (exists($changes{'internal.selfenroll_start_date'})) || + (exists($changes{'internal.selfenroll_end_date'}))) { + my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.', + $cnum,undef,undef,'Course'); + my $chome = &Apache::lonnet::homeserver($cnum,$cdom); + if (ref($crsinfo{$env{'request.course.id'}}) eq 'HASH') { + foreach my $item ('selfenroll_types','selfenroll_start_date','selfenroll_end_date') { + if (exists($changes{'internal.'.$item})) { + $crsinfo{$env{'request.course.id'}}{$item} = + $changes{'internal.'.$item}; + } + } + my $crsputresult = + &Apache::lonnet::courseidput($cdom,\%crsinfo, + $chome,'notime'); + } + } + $r->print(&mt('The following changes were made to self-enrollment settings:').'
    '); + foreach my $item (@{$row}) { + my $title = $item; + if (ref($lt) eq 'HASH') { + $title = $lt->{$item}; + } + if ($item eq 'enroll_dates') { + foreach my $type ('start','end') { + if (exists($changes{'internal.selfenroll_'.$type.'_date'})) { + my $newdate = &Apache::lonlocal::locallocaltime($changes{'internal.selfenroll_'.$type.'_date'}); + $r->print('
  • '.&mt('[_1]: "[_2]" set to "[_3]".', + $title,$type,$newdate).'
  • '); + } + } + } elsif ($item eq 'access_dates') { + foreach my $type ('start','end') { + if (exists($changes{'internal.selfenroll_'.$type.'_access'})) { + my $newdate = &Apache::lonlocal::locallocaltime($changes{'internal.selfenroll_'.$type.'_access'}); + $r->print('
  • '.&mt('[_1]: "[_2]" set to "[_3]".', + $title,$type,$newdate).'
  • '); + } + } + } elsif ($item eq 'limit') { + if ((exists($changes{'internal.selfenroll_limit'})) || + (exists($changes{'internal.selfenroll_cap'}))) { + my ($newval,$newcap); + if ($changes{'internal.selfenroll_cap'} ne '') { + $newcap = $changes{'internal.selfenroll_cap'} + } else { + $newcap = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_cap'}; + } + if ($changes{'internal.selfenroll_limit'} eq 'none') { + $newval = &mt('No limit'); + } elsif ($changes{'internal.selfenroll_limit'} eq + 'allstudents') { + $newval = &mt('New self-enrollment no longer allowed when total (all students) reaches [_1].',$newcap); + } elsif ($changes{'internal.selfenroll_limit'} eq 'selfenrolled') { + $newval = &mt('New self-enrollment no longer allowed when total number of self-enrolled students reaches [_1].',$newcap); + } else { + my $currlimit = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_limit'}; + if ($currlimit eq 'allstudents') { + $newval = &mt('New self-enrollment no longer allowed when total (all students) reaches [_1].',$newcap); + } elsif ($changes{'internal.selfenroll_limit'} eq 'selfenrolled') { + $newval = &mt('New self-enrollment no longer allowed when total number of self-enrolled students reaches [_1].',$newcap); + } + } + $r->print('
  • '.&mt('"[_1]" set to "[_2]".',$title,$newval).'
  • '."\n"); + } + } elsif ($item eq 'approval') { + if ((exists($changes{'internal.selfenroll_approval'})) || + (exists($changes{'internal.selfenroll_notifylist'}))) { + my ($newval,$newnotify); + if (exists($changes{'internal.selfenroll_notifylist'})) { + $newnotify = $changes{'internal.selfenroll_notifylist'}; + } else { + $newnotify = $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_notifylist'}; + } + if ($changes{'internal.selfenroll_approval'}) { + $newval = &mt('Yes'); + } elsif ($changes{'internal.selfenroll_approval'} eq '0') { + $newval = &mt('No'); + } else { + my $currapproval = + $env{'course.'.$env{'request.course.id'}.'.internal.selfenroll_approval'}; + if ($currapproval) { + $newval = &mt('Yes'); + } else { + $newval = &mt('No'); + } + } + $r->print('
  • '.&mt('"[_1]" set to "[_2]".',$title,$newval)); + if ($newnotify) { + $r->print('
    '.&mt('The following will be notified when an enrollment request needs approval, or has been approved: [_1].',$newnotify)); + } else { + $r->print('
    '.&mt('No notifications sent when an enrollment request needs approval, or has been approved.')); + } + $r->print('
  • '."\n"); + } + } else { + if (exists($changes{'internal.selfenroll_'.$item})) { + my $newval = $changes{'internal.selfenroll_'.$item}; + if ($item eq 'types') { + if ($newval eq '') { + $newval = &mt('None'); + } elsif ($newval eq '*') { + $newval = &mt('Any user in any domain'); + } + } elsif ($item eq 'registered') { + if ($newval eq '1') { + $newval = &mt('Yes'); + } elsif ($newval eq '0') { + $newval = &mt('No'); + } + } + $r->print('
  • '.&mt('"[_1]" set to "[_2]".',$title,$newval).'
  • '."\n"); + } + } + } + $r->print('
'); + my %newenvhash; + foreach my $key (keys(%changes)) { + $newenvhash{'course.'.$env{'request.course.id'}.'.'.$key} = $changes{$key}; + } + &Apache::lonnet::appenv(\%newenvhash); + } else { + $r->print(&mt('An error occurred when saving changes to self-enrollment settings in this course.').'
'.&mt('The error was: [_1].',$putresult)); + } + } else { + $r->print(&mt('No changes were made to the existing self-enrollment settings in this course.')); + } + } else { + $r->print(&mt('No changes were made to the existing self-enrollment settings in this course.')); + } + my ($visible,$cansetvis,$vismsgs,$visactions) = &visible_in_cat($cdom,$cnum); + if (ref($visactions) eq 'HASH') { + if (!$visible) { + $r->print('
'.$visactions->{'miss'}.'
'.$visactions->{'yous'}. + '
'); + if (ref($vismsgs) eq 'ARRAY') { + $r->print('
'.$visactions->{'take'}.'
    '); + foreach my $item (@{$vismsgs}) { + $r->print('
  • '.$visactions->{$item}.'
  • '); + } + $r->print('
'); + } + $r->print($cansetvis); + } + } + return; +} + +sub get_selfenroll_titles { + my @row = ('types','registered','enroll_dates','access_dates','section', + 'approval','limit'); + my %lt = &Apache::lonlocal::texthash ( + types => 'Users allowed to self-enroll in this course', + registered => 'Restrict self-enrollment to students officially registered for the course', + enroll_dates => 'Dates self-enrollment available', + access_dates => 'Course access dates assigned to self-enrolling users', + section => 'Section assigned to self-enrolling users', + approval => 'Self-enrollment requests need approval?', + limit => 'Enrollment limit', + ); + return (\@row,\%lt); +} + +sub is_courseowner { + my ($thiscourse,$courseowner) = @_; + if ($courseowner eq '') { + if ($env{'request.course.id'} eq $thiscourse) { + $courseowner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'}; + } + } + if ($courseowner ne '') { + if ($courseowner eq $env{'user.name'}.':'.$env{'user.domain'}) { + return 1; + } + } + return; +} + #---------------------------------------------- end functions for &phase_two #--------------------------------- functions for &phase_two and &phase_three