--- loncom/interface/loncreateuser.pm 2002/09/05 16:44:22 1.39.6.1 +++ loncom/interface/loncreateuser.pm 2022/11/16 14:47:57 1.406.2.20.2.2 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Create a user # -# $Id: loncreateuser.pm,v 1.39.6.1 2002/09/05 16:44:22 albertel Exp $ +# $Id: loncreateuser.pm,v 1.406.2.20.2.2 2022/11/16 14:47:57 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,833 +25,9585 @@ # # http://www.lon-capa.org/ # -# (Create a course -# (My Desk -# -# (Internal Server Error Handler -# -# (Login Screen -# 5/21/99,5/22,5/25,5/26,5/31,6/2,6/10,7/12,7/14, -# 1/14/00,5/29,5/30,6/1,6/29,7/1,11/9 Gerd Kortemeyer) -# -# YEAR=2001 -# 3/1/1 Gerd Kortemeyer) -# -# 3/1 Gerd Kortemeyer) -# -# 2/14 Gerd Kortemeyer) -# -# 2/14,2/17,2/19,2/20,2/21,2/22,2/23,3/2,3/17,3/24,04/12 Gerd Kortemeyer -# April Guy Albertelli -# 05/10,10/16 Gerd Kortemeyer -# 11/12,11/13,11/15 Scott Harrison -# 02/11/02 Matthew Hall -# -# $Id: loncreateuser.pm,v 1.39.6.1 2002/09/05 16:44:22 albertel Exp $ ### package Apache::loncreateuser; +=pod + +=head1 NAME + +Apache::loncreateuser.pm + +=head1 SYNOPSIS + + 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. + +=head1 OVERVIEW + +=head2 Custom Roles + +In LON-CAPA, roles are actually collections of privileges. "Teaching +Assistant", "Course Coordinator", and other such roles are really just +collection of privileges that are useful in many circumstances. + +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 creator +of the role. + +=cut + use strict; use Apache::Constants qw(:common :http); use Apache::lonnet; +use Apache::loncommon; +use Apache::lonlocal; +use Apache::longroup; +use Apache::lonuserutils; +use Apache::loncoursequeueadmin; +use LONCAPA qw(:DEFAULT :match); +use HTML::Entities; my $loginscript; # piece of javascript used in two separate instances -my $generalrule; my $authformnop; my $authformkrb; my $authformint; my $authformfsys; my $authformloc; -BEGIN { - $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/; - my $krbdefdom=$1; - $krbdefdom=~tr/a-z/A-Z/; - my %param = ( formname => 'document.cu', - kerb_def_dom => $krbdefdom - ); +sub initialize_authen_forms { + 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); - $generalrule = &Apache::loncommon::authform_authorwarning(%param); - $authformnop = &Apache::loncommon::authform_nochange(%param); $authformkrb = &Apache::loncommon::authform_kerberos(%param); + $authformnop = &Apache::loncommon::authform_nochange(%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', + localauth => 'loc', + unix => 'fsys', + ); + return %abv_auth; +} + +# ==================================================== + +sub user_quotas { + my ($ccuname,$ccdomain) = @_; + my %lt = &Apache::lonlocal::texthash( + 'usrt' => "User Tools", + 'cust' => "Custom quota", + 'chqu' => "Change quota", + ); + + my $quota_javascript = <<"END_SCRIPT"; + +END_SCRIPT + my $longinsttype; + my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($ccdomain); + my $output = $quota_javascript."\n". + '

'.$lt{'usrt'}.'

'."\n". + &Apache::loncommon::start_data_table(); + + if ((&Apache::lonnet::allowed('mut',$ccdomain)) || + (&Apache::lonnet::allowed('udp',$ccdomain))) { + $output .= &build_tools_display($ccuname,$ccdomain,'tools'); + } + + my %titles = &Apache::lonlocal::texthash ( + portfolio => "Disk space allocated to user's portfolio files", + author => "Disk space allocated to user's Authoring Space (if role assigned)", + ); + foreach my $name ('portfolio','author') { + my ($currquota,$quotatype,$inststatus,$defquota) = + &Apache::loncommon::get_user_quota($ccuname,$ccdomain,$name); + if ($longinsttype eq '') { + if ($inststatus ne '') { + if ($usertypes->{$inststatus} ne '') { + $longinsttype = $usertypes->{$inststatus}; + } + } + } + my ($showquota,$custom_on,$custom_off,$defaultinfo); + $custom_on = ' '; + $custom_off = ' checked="checked" '; + 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); + } + } + + if (&Apache::lonnet::allowed('mpq',$ccdomain)) { + $output .= ''."\n". + ' '.$titles{$name}.''."\n". + ' '."\n". + &Apache::loncommon::start_data_table_row()."\n". + ' '. + &mt('Current quota: [_1] MB',$currquota).'  '. + $defaultinfo.''."\n". + &Apache::loncommon::end_data_table_row()."\n". + &Apache::loncommon::start_data_table_row()."\n". + ' '.$lt{'chqu'}. + ':  '. + '  '. + ' '.&mt('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", + 'webdav' => "WebDAV access to Authoring Spaces (if SSL and author/co-author)", + 'portfolio' => "Personal User Portfolio", + 'timezone' => "Can set Time Zone", + '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', + 'textbook' => 'Can request creation of textbook courses', + 'requestauthor' => 'Can request author space', + ); + $isadv = &Apache::lonnet::is_advanced_user($ccdomain,$ccuname); + if ($context eq 'requestcourses') { + %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname, + 'requestcourses.official','requestcourses.unofficial', + 'requestcourses.community','requestcourses.textbook'); + @usertools = ('official','unofficial','community','textbook'); + @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); + } elsif ($context eq 'requestauthor') { + %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname, + 'requestauthor'); + @usertools = ('requestauthor'); + @options =('norequest','approval','automatic'); + %reqtitles = &requestauthor_titles(); + %reqdisplay = &requestauthor_display(); + $colspan = ' colspan="2"'; + %domconfig = + &Apache::lonnet::get_dom('configuration',['requestauthor'],$ccdomain); + } else { + %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname, + 'tools.aboutme','tools.portfolio','tools.blog', + 'tools.webdav','tools.timezone'); + @usertools = ('aboutme','blog','webdav','portfolio','timezone'); + } + 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,\%userenv,'', + {'is_adv' => $isadv}); + if ($context eq 'requestauthor') { + if ($userenv{$context} ne '') { + $cust_on = ' checked="checked" '; + $cust_off = ''; + } + } elsif ($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.'); + } + } elsif ($context eq 'requestauthor') { + if ($userenv{$context} 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') || ($context eq 'requestauthor')) { + my ($curroption,$currlimit); + my $envkey = $context.'.'.$item; + if ($context eq 'requestauthor') { + $envkey = $context; + } + if ($userenv{$envkey} ne '') { + $curroption = $userenv{$envkey}; + } else { + my (@inststatuses); + if ($context eq 'requestcourses') { + $curroption = + &Apache::loncoursequeueadmin::get_processtype('course',$ccuname,$ccdomain, + $isadv,$ccdomain,$item, + \@inststatuses,\%domconfig); + } else { + $curroption = + &Apache::loncoursequeueadmin::get_processtype('requestauthor',$ccuname,$ccdomain, + $isadv,$ccdomain,undef, + \@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"'; + } + } + my $name = 'crsreq_'.$item; + if ($context eq 'requestauthor') { + $name = $item; + } + $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')); + my $name = $context.'_'.$item; + if ($context eq 'requestauthor') { + $name = $context; + } + $custdisp = ' '; + $custradio = (' 'x2).'--'.$lt{'cusa'}.': '.$custdisp. + ''; + } + $output .= ' '.$custom_access.(' 'x4). + $lt{'avai'}.': '.$currdisp.''."\n". + &Apache::loncommon::end_data_table_row()."\n"; + unless (&Apache::lonnet::allowed('udp',$ccdomain)) { + $output .= + &Apache::loncommon::start_data_table_row()."\n". + ' '. + $lt{'chse'}.': '.(' ' x3). + ''.$custradio.''. + &Apache::loncommon::end_data_table_row()."\n"; + } + } + return $output; +} + +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', + 'textbook' => 'Can request creation of textbook courses', + ); + + %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname, + 'reqcrsotherdom.official','reqcrsotherdom.unofficial', + 'reqcrsotherdom.community','reqcrsotherdom.textbook'); + @usertools = ('official','unofficial','community','textbook'); + @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 domainrole_req { + my ($ccuname,$ccdomain) = @_; + return '

'. + &mt('User Can Request Assignment of Domain Roles?'). + '

'."\n". + &Apache::loncommon::start_data_table(). + &build_tools_display($ccuname,$ccdomain, + 'requestauthor'). + &Apache::loncommon::end_data_table(); +} + +sub courserequest_titles { + my %titles = &Apache::lonlocal::texthash ( + official => 'Official', + unofficial => 'Unofficial', + community => 'Communities', + textbook => 'Textbook', + 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; +} + +sub requestauthor_titles { + my %titles = &Apache::lonlocal::texthash ( + norequest => 'Not allowed', + approval => 'Approval by Dom. Coord.', + automatic => 'Automatic approval', + ); + return %titles; + +} + +sub requestauthor_display { + my %titles = &Apache::lonlocal::texthash ( + approval => 'Yes, need approval', + automatic => 'Yes, automatic approval', + norequest => 'No', + ); + return %titles; +} + +sub requestchange_display { + my %titles = &Apache::lonlocal::texthash ( + approval => "availability set to 'on' (approval required)", + automatic => "availability set to 'on' (automatic approval)", + norequest => "availability set to 'off'", + ); + return %titles; +} + +sub curr_requestauthor { + my ($uname,$udom,$isadv,$inststatuses,$domconfig) = @_; + return unless ((ref($inststatuses) eq 'ARRAY') && (ref($domconfig) eq 'HASH')); + if ($uname eq '' || $udom eq '') { + $uname = $env{'user.name'}; + $udom = $env{'user.domain'}; + $isadv = $env{'user.adv'}; + } + my (%userenv,%settings,$val); + my @options = ('automatic','approval'); + %userenv = + &Apache::lonnet::userenvironment($udom,$uname,'requestauthor','inststatus'); + if ($userenv{'requestauthor'}) { + $val = $userenv{'requestauthor'}; + @{$inststatuses} = ('_custom_'); + } else { + my %alltasks; + if (ref($domconfig->{'requestauthor'}) eq 'HASH') { + %settings = %{$domconfig->{'requestauthor'}}; + if (($isadv) && ($settings{'_LC_adv'} ne '')) { + $val = $settings{'_LC_adv'}; + @{$inststatuses} = ('_LC_adv_'); + } else { + if ($userenv{'inststatus'} ne '') { + @{$inststatuses} = split(',',$userenv{'inststatus'}); + } else { + @{$inststatuses} = ('default'); + } + foreach my $status (@{$inststatuses}) { + if (exists($settings{$status})) { + my $value = $settings{$status}; + next unless ($value); + unless (exists($alltasks{$value})) { + if (ref($alltasks{$value}) eq 'ARRAY') { + unless(grep(/^\Q$status\E$/,@{$alltasks{$value}})) { + push(@{$alltasks{$value}},$status); + } + } else { + @{$alltasks{$value}} = ($status); + } + } + } + } + foreach my $option (@options) { + if ($alltasks{$option}) { + $val = $option; + last; + } + } + } + } + } + return $val; +} + # =================================================================== Phase one sub print_username_entry_form { - my $r=shift; - my $defdom=$ENV{'request.role.domain'}; - my @domains = &Apache::loncommon::get_domains(); - my $domform = &Apache::loncommon::select_dom_form($defdom,'ccdomain'); - $r->print(<<"ENDDOCUMENT"); - - -The LearningOnline Network with CAPA - - -

Create User, Change User Privileges

-
- -

-Username:
-Domain: $domform -

- -
- - -ENDDOCUMENT -} + my ($r,$context,$response,$srch,$forcenewuser,$crstype,$brcrum, + $permission) = @_; + my $defdom=$env{'request.role.domain'}; + 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'}; + } -# =================================================================== Phase two -sub print_user_modification_page { - my $r=shift; - my $ccuname=$ENV{'form.ccuname'}; - my $ccdomain=$ENV{'form.ccdomain'}; - - $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/; - my $krbdefdom=$1; - $krbdefdom=~tr/a-z/A-Z/; - my %param = ( formname => 'document.cu', - kerb_def_dom => $krbdefdom + 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') { + if ($context eq 'course') { + $helpitem = 'Course_Editing_Custom_Roles'; + } elsif ($context eq 'domain') { + $helpitem = 'Domain_Editing_Custom_Roles'; + } + } elsif ($env{'form.action'} eq 'singlestudent') { + $helpitem = 'Course_Add_Student'; + } elsif ($env{'form.action'} eq 'accesslogs') { + $helpitem = 'Domain_User_Access_Logs'; + } elsif ($context eq 'author') { + $helpitem = 'Author_Change_Privileges'; + } elsif ($context eq 'domain') { + if ($permission->{'cusr'}) { + $helpitem = 'Domain_Change_Privileges'; + } elsif ($permission->{'view'}) { + $helpitem = 'Domain_View_Privileges'; + } else { + undef($helpitem); + } + } + my %breadcrumb_text = &singleuser_breadcrumb($crstype,$context,$defdom); + 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',} ); - $loginscript = &Apache::loncommon::authform_header(%param); + } + 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 $defdom=$ENV{'request.role.domain'}; + my %lt=&Apache::lonlocal::texthash( + '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', + 'srvu' => 'Search for a user and view user information and roles', + 'srva' => 'Search for a user and view access log information', + 'usr' => "Username", + 'dom' => "Domain", + 'ecrp' => "Define or Edit Custom Role", + 'nr' => "role name", + 'cre' => "Next", + ); - $ccuname=~s/\W//g; - $ccdomain=~s/\W//g; - my $dochead =<<"ENDDOCHEAD"; - - -The LearningOnline Network with CAPA - +END + return $js; +} +sub entry_form { + my ($dom,$srch,$forcenewuser,$context,$responsemsg,$crstype,$fixeddom) = @_; + 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 (%curr_rules,%got_rules); + my ($rules,$ruleorder) = + &Apache::lonnet::inst_userrules($srch->{'srchdomain'},'username'); + $usertype = &Apache::lonuserutils::check_usertype($srch->{'srchdomain'},$srch->{'srchterm'},$rules,\%curr_rules,\%got_rules); + } else { + $inexact = 1; + } + } + my ($cancreate,$noinstd); + if ($env{'form.action'} eq 'accesslogs') { + $noinstd = 1; + } else { + $cancreate = + &Apache::lonuserutils::can_create_user($dom,$context,$usertype); + } + my ($userpicker,$cansearch) = + &Apache::loncommon::user_picker($dom,$srch,$forcenewuser, + 'document.crtuser',$cancreate,$usertype,$context,$fixeddom,$noinstd); + my $srchbutton = &mt('Search'); + if ($env{'form.action'} eq 'singlestudent') { + $srchbutton = &mt('Search and Enroll'); + } elsif ($env{'form.action'} eq 'accesslogs') { + $srchbutton = &mt('Search'); + } elsif ($cancreate && $responsemsg ne '' && $inexact) { + $srchbutton = &mt('Search or Add New User'); + } + my $output; + if ($cansearch) { + $output = <<"ENDBLOCK"; +
+ + +$userpicker + +
+ENDBLOCK + } else { + $output = '

'.$userpicker.'

'; + } + if (($env{'form.phase'} eq '') && ($env{'form.action'} ne 'accesslogs') && + (!(($env{'form.action'} eq 'singleuser') && ($context eq 'domain') && + (!&Apache::lonnet::allowed('mau',$env{'request.role.domain'}))))) { + 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'}: $lt{'dom'}:$domform $sellink  
+
+ENDDOCUMENT } + return $output; +} + +sub user_modification_js { + my ($pjump_def,$dc_setcourse_code,$nondc_setsection_code,$groupslist)=@_; + + return < +// + +END +} + +# =================================================================== Phase two +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 = (< +// - - - -ENDDOCHEAD +ENDSCRIPT + + my %lt=&Apache::lonlocal::texthash( + 'usrch' => "User Search to add/modify roles", + 'stusrch' => "User Search to enroll student", + 'memsrch' => "User Search to enroll member", + 'srcva' => "Search for a user and view access log information", + 'usrvu' => "User Search to view user roles", + 'usel' => "Select a user to add/modify roles", + 'suvr' => "Select a user to view roles", + 'stusel' => "Select a user to enroll as a student", + 'memsel' => "Select a user to enroll as a member", + 'vacsel' => "Select a user to view access log", + 'username' => "username", + 'domain' => "domain", + 'lastname' => "last name", + 'firstname' => "first name", + 'permanentemail' => "permanent e-mail", + ); + if ($context eq 'requestcrs') { + $r->print('
'); + } else { + my %breadcrumb_text = &singleuser_breadcrumb($crstype,$context,$srch->{'srchdomain'}); + my $helpitem; + if ($env{'form.action'} eq 'singleuser') { + $helpitem = 'Course_Change_Privileges'; + } elsif ($env{'form.action'} eq 'singlestudent') { + $helpitem = 'Course_Add_Student'; + } elsif ($context eq 'author') { + $helpitem = 'Author_Change_Privileges'; + } elsif ($context eq 'domain') { + $helpitem = 'Domain_Change_Privileges'; + } + 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} + ); + $r->print(&Apache::loncommon::start_page('User Management',$jscript,{bread_crumbs => $brcrum})); + if ($env{'form.action'} eq 'singleuser') { + my $readonly; + if (($context eq 'domain') && (!&Apache::lonnet::allowed('mau',$srch->{'srchdomain'}))) { + $readonly = 1; + $r->print("$lt{'usrvu'}
"); + } else { + $r->print("$lt{'usrch'}
"); + } + $r->print(&entry_form($srch->{'srchdomain'},$srch,undef,$context,undef,$crstype)); + if ($readonly) { + $r->print('

'.$lt{'suvr'}.'

'); + } else { + $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'}); + } + $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('

'); + } elsif ($env{'form.action'} eq 'accesslogs') { + $r->print("$lt{'srcva'}
"); + $r->print(&entry_form($srch->{'srchdomain'},$srch,undef,$context,undef,undef,1)); + $r->print('

'.$lt{'vacsel'}.'

'); + } + } + $r->print('
'. + &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."'".');"'; + } + $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()); + } + $r->print(&Apache::loncommon::end_data_table().'

'); + if (ref($srcharray) eq 'ARRAY') { + foreach my $item (@{$srcharray}) { + $r->print(''."\n"); + } + } + $r->print(' '."\n". + ' '."\n". + ' '."\n". + ' '."\n". + ' '."\n". + ' '."\n"); + if ($context eq 'requestcrs') { + $r->print($opener_elements.'
'); + } else { + $r->print($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,$showcredits) = @_; + 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, + $permission); + 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, + \%curr_rules,\%got_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.") + .' '; + if ($context eq 'domain') { + $response .= &mt('Please contact a [_1] for assistance.', + &Apache::lonnet::plaintext('dc')); + } else { + $response .= &mt('Please contact the [_1]helpdesk[_2] for assistance.' + ,'',''); + } + $response .= '


'; + $env{'form.phase'} = ''; + &print_username_entry_form($r,$context,$response,undef,undef,$crstype,$brcrum, + $permission); + 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, + $permission); + return; + } + } + } + } else { + $newuser = 0; + } + if ($response) { + $response = '
'.$response; + } + + 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,$crstype, + $groupslist,$newuser,$formname,\%loaditem); + my %breadcrumb_text = &singleuser_breadcrumb($crstype,$context,$ccdomain); + my $helpitem = 'Course_Change_Privileges'; + if ($env{'form.action'} eq 'singlestudent') { + $helpitem = 'Course_Add_Student'; + } elsif ($context eq 'author') { + $helpitem = 'Author_Change_Privileges'; + } elsif ($context eq 'domain') { + $helpitem = 'Domain_Change_Privileges'; + } + 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 (%Apache::lonnet::hostdom) { - $incdomains{$_}=1; - } - foreach (keys(%ENV)) { - if ($_=~/^user\.priv\.cm\.\/(\w+)\/(\w+)/) { - $inccourses{$1.'_'.$2}=1; + my (%inccourses,$roledom,$defaultcredits); + if ($context eq 'course') { + $inccourses{$env{'request.course.id'}}=1; + $roledom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + if ($showcredits) { + $defaultcredits = &Apache::lonuserutils::get_defaultcredits(); + } + } 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); - - $r->print(<Create New User + my $title = ''; + if ($newuser) { + my ($portfolioform,$domroleform); + 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 = '
'.&user_quotas($ccuname,$ccdomain); + } + if ((&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) && + ($ccdomain eq $env{'request.role.domain'})) { + $domroleform = '
'.&domainrole_req($ccuname,$ccdomain); + } + &initialize_authen_forms($ccdomain,$formname); + my %lt=&Apache::lonlocal::texthash( + 'lg' => 'Login Data', + 'hs' => "Home Server", + ); + $r->print(<New user "$ccuname" in domain $ccdomain -

Personal Data

-

- - - - - - - - - -
First Name
Middle Name
Last Name
Generation
-ID/Student Number

-Home Server: -
-

Login Data

-

$generalrule

-

$authformkrb

-

$authformint

-

$authformfsys

-

$authformloc

-ENDNEWUSER +ENDTITLE + if ($env{'form.action'} eq 'singlestudent') { + if ($crstype eq 'Community') { + $title = &mt('Create New User [_1] in domain [_2] as a member', + '"'.$ccuname.'"','"'.$ccdomain.'"'); + } else { + $title = &mt('Create New User [_1] in domain [_2] as a student', + '"'.$ccuname.'"','"'.$ccdomain.'"'); + } + } else { + $title = &mt('Create New User [_1] in domain [_2]', + '"'.$ccuname.'"','"'.$ccdomain.'"'); + } + $r->print('

'.$title.'

'."\n"); + $r->print('
'); + $r->print(&personal_data_display($ccuname,$ccdomain,$newuser,$context, + $inst_results{$ccuname.':'.$ccdomain})); + # Option to disable student/employee ID conflict checking not offerred for new users. + 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.$domroleform); + if ($env{'form.action'} eq 'singlestudent') { + $r->print(&date_sections_select($context,$newuser,$formname, + $permission,$crstype,$ccuname, + $ccdomain,$showcredits)); + } + $r->print('
'); } else { # user already exists - $r->print(<Change User Privileges -$forminfo -

User "$ccuname" in domain $ccdomain

-ENDCHANGEUSER - # Get the users information - my %userenv = &Apache::lonnet::get('environment', - ['firstname','middlename','lastname','generation'], - $ccdomain,$ccuname); - my %rolesdump=&Apache::lonnet::dump('roles',$ccdomain,$ccuname); - $r->print(< - - - - - -END - foreach ('firstname','middlename','lastname','generation') { - if (&Apache::lonnet::allowed('mau',$ccdomain)) { - $r->print(<<"END"); - -END - } else { - $r->print(''); - } + $r->print($start_page.$forminfo); + if ($env{'form.action'} eq 'singlestudent') { + if ($crstype eq 'Community') { + $title = &mt('Enroll one member: [_1] in domain [_2]', + '"'.$ccuname.'"','"'.$ccdomain.'"'); + } else { + $title = &mt('Enroll one student: [_1] in domain [_2]', + '"'.$ccuname.'"','"'.$ccdomain.'"'); + } + } else { + if ($permission->{'cusr'}) { + $title = &mt('Modify existing user: [_1] in domain [_2]', + '"'.$ccuname.'"','"'.$ccdomain.'"'); + } else { + $title = &mt('Existing user: [_1] in domain [_2]', + '"'.$ccuname.'"','"'.$ccdomain.'"'); + } } - $r->print(< -
first namemiddle namelast namegeneration
'.$userenv{$_}.'
-END - # 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; - $r->print(< -

Revoke Existing Roles

- - -END - foreach my $area (keys(%rolesdump)) { - next if ($area =~ /^rolesdef/); - my $role = $rolesdump{$area}; - my $thisrole=$area; - $area =~ s/\_\w\w$//; - my ($role_code,$role_end_time,$role_start_time) = - split(/_/,$role); - my $bgcol='ffffff'; - my $allowed=0; - if ($area =~ /^\/(\w+)\/(\d\w+)/ ) { - my %coursedata= - &Apache::lonnet::coursedescription($1.'_'.$2); - my $carea='Course: '.$coursedata{'description'}; - $inccourses{$1.'_'.$2}=1; - if (&Apache::lonnet::allowed('c'.$role_code,$1.'/'.$2)) { - $allowed=1; - } - # Compute the background color based on $area - $bgcol=$1.'_'.$2; - $bgcol=~s/[^8-9b-e]//g; - $bgcol=substr($bgcol.$bgcol.$bgcol.'ffffff',0,6); - if ($area=~/^\/(\w+)\/(\d\w+)\/(\w+)/) { - $carea.='
Section/Group: '.$3; - } - $area=$carea; - } else { - # Determine if current user is able to revoke privileges - if ($area=~ /^\/(\w+)\//) { - if (&Apache::lonnet::allowed('c'.$role_code,$1)) { - $allowed=1; - } - } else { - if (&Apache::lonnet::allowed('c'.$role_code,'/')) { - $allowed=1; - } - } - } - # I have no idea what the hell the above code does - # So the following is a check: - if ($allowed) { - # If we are looking at a co-author role, make sure it is - # for the current users construction space before we let - # them revoke it. - if (($role_code eq 'ca') && - ($ENV{'request.role'} !~ /^dc/)) { - if ($area !~ - /^\/$ENV{'request.role.domain'}\/$ENV{'user.name'}/) { - $allowed = 0; - } - } - } - my $row = ''; - $row.='\n"; - $r->print($row); - } # end of foreach (table building loop) - $r->print('
RevokeRoleExtentStartEnd
'; - my $active=1; - $active=0 if (($role_end_time) && ($now>$role_end_time)); - if (($active) && ($allowed)) { - $row.= ''; - } else { - $row.=' '; - } - $row.= ''.&Apache::lonnet::plaintext($role_code). - ''.$area. - ''.($role_start_time?localtime($role_start_time) - : ' ' ). - ''.($role_end_time ?localtime($role_end_time) - : ' ' ) - ."
'); - } # End of unless - my $currentauth=&Apache::lonnet::queryauthenticate($ccuname,$ccdomain); - if ($currentauth=~/^krb(4|5):/) { - $currentauth=~/^krb(4|5):(.*)/; - my $krbdefdom2=$1; - 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',$ENV{'request.role.domain'})) { - $r->print(< + $r->print('

'.$title.'

'."\n"); + $r->print('
'); + $r->print(&personal_data_display($ccuname,$ccdomain,$newuser,$context, + $inst_results{$ccuname.':'.$ccdomain})); + if ((&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) || + (&Apache::lonnet::allowed('udp',$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 @order = ('auth','quota','tools','requestauthor'); + my %user_text; + my ($isadv,$isauthor) = + &Apache::lonnet::is_advanced_user($ccdomain,$ccuname); + if ((!$isauthor) && + ((&Apache::lonnet::allowed('cau',$env{'request.role.domain'})) || + (&Apache::lonnet::allowed('udp',$env{'request.role.domain'}))) && + ($env{'request.role.domain'} eq $ccdomain)) { + $user_text{'requestauthor'} = &domainrole_req($ccuname,$ccdomain); + } + $user_text{'auth'} = &user_authentication($ccuname,$ccdomain,$formname,$crstype,$permission); + if ((&Apache::lonnet::allowed('mpq',$ccdomain)) || + (&Apache::lonnet::allowed('mut',$ccdomain)) || + (&Apache::lonnet::allowed('udp',$ccdomain))) { + # Current user has quota modification privileges + $user_text{'quota'} = &user_quotas($ccuname,$ccdomain); + } + if (!&Apache::lonnet::allowed('mpq',$ccdomain)) { + if (&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) { + my %lt=&Apache::lonlocal::texthash( + 'dska' => "Disk quotas for user's portfolio and Authoring Space", + 'youd' => "You do not have privileges to modify the portfolio and/or Authoring Space quotas for this user.", + 'ichr' => "If a change is required, contact a domain coordinator for the domain", + ); + $user_text{'quota'} = <$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, WebDAV, or Personal Information Page settings for this user.", + 'ifch' => "If a change is required, contact a domain coordinator for the domain", + ); + $user_text{'tools'} = <$lt{'utav'} +$lt{'yodo'} $lt{'ifch'}: $ccdomain +ENDNOTOOLSPRIV + } + } + my $gotdiv = 0; + foreach my $item (@order) { + if ($user_text{$item} ne '') { + unless ($gotdiv) { + $r->print('
'); + $gotdiv = 1; + } + $r->print('
'.$user_text{$item}); + } + } + if ($env{'form.action'} eq 'singlestudent') { + unless ($gotdiv) { + $r->print('
'); + } + my $credits; + if ($showcredits) { + $credits = &get_user_credits($ccuname,$ccdomain,$defaultcredits); + if ($credits eq '') { + $credits = $defaultcredits; + } + } + $r->print(&date_sections_select($context,$newuser,$formname, + $permission,$crstype,$ccuname, + $ccdomain,$showcredits)); + } + if ($gotdiv) { + $r->print('
'); + } + my $statuses; + if (($context eq 'domain') && (&Apache::lonnet::allowed('udp',$ccdomain)) && + (!&Apache::lonnet::allowed('mau',$ccdomain))) { + $statuses = ['active']; + } elsif (($context eq 'course') && ((&Apache::lonnet::allowed('vcl',$env{'request.course.id'})) || + ($env{'request.course.sec'} && + &Apache::lonnet::allowed('vcl',$env{'request.course.id'}.'/'.$env{'request.course.sec'})))) { + $statuses = ['active']; + } + if ($env{'form.action'} ne 'singlestudent') { + &display_existing_roles($r,$ccuname,$ccdomain,\%inccourses,$context, + $roledom,$crstype,$showcredits,$statuses); + } + } ## 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('
'."\n"); + } elsif ($permission->{'cusr'}) { + $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,$ccdomain); + if (!$addrolesdisplay) { + $addrolesdisplay = $add_domainroles; + } + $r->print(&course_level_dc($env{'request.role.domain'},$showcredits)); + $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,$showcredits,$defaultcredits)); + $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,$context,$domain) = @_; + 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'; + } elsif ($env{'form.action'} eq 'accesslogs') { + $breadcrumb_text{'search'} = 'View access logs for a user'; + $breadcrumb_text{'userpicked'} = 'Select a user'; + $breadcrumb_text{'activity'} = 'Activity'; + } elsif (($env{'form.action'} eq 'singleuser') && ($context eq 'domain') && + (!&Apache::lonnet::allowed('mau',$domain))) { + $breadcrumb_text{'search'} = "View user's roles"; + $breadcrumb_text{'userpicked'} = 'Select a user'; + $breadcrumb_text{'modify'} = 'User roles'; + } 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,$crstype,$ccuname,$ccdomain, + $showcredits) = @_; + my $credits; + if ($showcredits) { + my $defaultcredits = &Apache::lonuserutils::get_defaultcredits(); + $credits = &get_user_credits($ccuname,$ccdomain,$defaultcredits); + if ($credits eq '') { + $credits = $defaultcredits; + } + } + 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 and Credits').'

'."\n". + &Apache::lonuserutils::section_picker($cdom,$cnum,'st',$rowtitle, + $permission,$context,'',$crstype, + $showcredits,$credits); + my $output = $date_table.$secbox; + return $output; +} + +sub validation_javascript { + my ($context,$ccdomain,$pjump_def,$crstype,$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, + $crstype); + } + 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, + $showcredits,$statuses) = @_; + my $now=time; + my $showall = 1; + my ($showexpired,$showactive); + if ((ref($statuses) eq 'ARRAY') && (@{$statuses} > 0)) { + $showall = 0; + if (grep(/^expired$/,@{$statuses})) { + $showexpired = 1; + } + if (grep(/^active$/,@{$statuses})) { + $showactive = 1; + } + if ($showexpired && $showactive) { + $showall = 1; + } + } + my %lt=&Apache::lonlocal::texthash( + 'rer' => "Existing Roles", + 'rev' => "Revoke", + 'del' => "Delete", + 'ren' => "Re-Enable", + 'rol' => "Role", + 'ext' => "Extent", + 'crd' => "Credits", + 'sta' => "Start", + '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 { + %rolesdump=&Apache::lonnet::dump('roles',$ccdomain,$ccuname); + } + # 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); + my $active=1; + $active=0 if (($role_end_time) && ($now>$role_end_time)); + if ($active) { + next unless($showall || $showactive); + } else { + next unless($showall || $showexpired); + } +# Is this a custom role? Get role owner and title. + 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'; + my $credits=''; + my $csec; + 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). + next if ($envkey =~ m{^/$match_domain/$match_courseid/[A-Za-z0-9]+_gr$}); + 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 (($showcredits) && ($class eq 'Course') && ($role_code eq 'st')) { + my $defaultcredits = $coursedata{'internal.defaultcredits'}; + $credits = + &get_user_credits($ccuname,$ccdomain,$defaultcredits, + $coursedom,$coursedir); + if ($credits eq '') { + $credits = $defaultcredits; + } + } + if ((&Apache::lonnet::allowed('c'.$role_code,$coursedom.'/'.$coursedir)) || + (&Apache::lonnet::allowed('c'.$role_code,$ccdomain))) { + $allowed=1; + } + unless ($allowed) { + my $isowner = &Apache::lonuserutils::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',$coursedom.'/'.$coursedir)) { + $allowed=1; + $thisrole.='.'.$role_code; + } + } + if ($area=~m{^/($match_domain/$match_courseid/(\w+))}) { + $csec = $2; + $carea.='
'.&mt('Section: [_1]',$csec); + $sortkey.="\0$csec"; + if (!$allowed) { + if ($env{'request.course.sec'} eq $csec) { + if (&Apache::lonnet::allowed('c'.$role_code,$1)) { + $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' || $role_code eq 'aa') { + $class='Authoring 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 = ''; + if ($showall) { + $row.= ''; + 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.=' '; + } + $row.= ''; + } + my $plaintext=''; + if (!$croletitle) { + $plaintext=&Apache::lonnet::plaintext($role_code,$class); + if (($showcredits) && ($credits ne '')) { + $plaintext .= '
'. + ''. + &mt('Credits: [_1]',$credits). + ''; + } + } else { + $plaintext= + &mt('Custom role [_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; + if ($allowed) { + $rolepriv{$envkey}='edit'; + } else { + if ($context eq 'domain') { + if ((&Apache::lonnet::allowed('vur',$ccdomain)) && + ($envkey=~m{^/$ccdomain/})) { + $rolepriv{$envkey}='view'; + } + } elsif ($context eq 'course') { + if ((&Apache::lonnet::allowed('vcl',$env{'request.course.id'})) || + ($env{'request.course.sec'} && ($env{'request.course.sec'} eq $csec) && + &Apache::lonnet::allowed('vcl',$env{'request.course.id'}.'/'.$env{'request.course.sec'}))) { + $rolepriv{$envkey}='view'; + } + } + } + } # end of foreach (table building loop) + + my $rolesdisplay = 0; + my %output = (); + foreach my $type ('Authoring 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 Authoring Space'); + } else { + if ($showall) { + $contextrole = &mt('Existing Roles in this Domain'); + } elsif ($showactive) { + $contextrole = &mt('Unexpired Roles in this Domain'); + } elsif ($showexpired) { + $contextrole = &mt('Expired or Revoked Roles in this Domain'); + } + } + $r->print('
'. +'
'.$contextrole.''. +&Apache::loncommon::start_data_table("LC_createuser"). +&Apache::loncommon::start_data_table_header_row()); + if ($showall) { + $r->print( +''.$lt{'rev'}.''.$lt{'ren'}.''.$lt{'del'}.'' + ); + } elsif ($showexpired) { + $r->print(''.$lt{'rev'}.''); + } + $r->print( +''.$lt{'rol'}.''.$lt{'ext'}.''. +''.$lt{'sta'}.''.$lt{'end'}.''. +&Apache::loncommon::end_data_table_header_row()); + foreach my $type ('Authoring Space','Course','Community','Domain','System','Unknown') { + if ($output{$type}) { + $r->print($output{$type}."\n"); + } + } + $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 + $addrolesdisplay = 1; + my $cuname=$env{'user.name'}; + my $cudom=$env{'request.role.domain'}; + my %lt=&Apache::lonlocal::texthash( + 'cs' => "Authoring Space", + 'act' => "Activate", + 'rol' => "Role", + 'ext' => "Extent", + 'sta' => "Start", + 'end' => "End", + 'cau' => "Co-Author", + '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().' + + + + '.$lt{'cau'}.' + '.$cudom.'_'.$cuname.' + + '.$lt{'ssd'}.' + +'.$lt{'sed'}.''."\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()); + } 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 Authoring Space is not permitted')); + } + } + return $addrolesdisplay;; +} + +sub new_domain_roles { + my ($r,$ccdomain) = @_; + my $addrolesdisplay = 0; + # + # Domain level + # + my $num_domain_level = 0; + my $domaintext = + '

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

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ''.&mt('Activate').''.&mt('Role').''. + &mt('Extent').''. + ''.&mt('Start').''.&mt('End').''. + &Apache::loncommon::end_data_table_header_row(); + 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'); + next if (($role eq 'au') && ($ccdomain ne $thisdomain)); + if (&Apache::lonnet::allowed('c'.$role,$thisdomain)) { + my $plrole=&Apache::lonnet::plaintext($role); + my %lt=&Apache::lonlocal::texthash( + 'ssd' => "Set Start Date", + 'sed' => "Set End Date" + ); + $num_domain_level ++; + $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; + } + return $addrolesdisplay; +} + +sub user_authentication { + my ($ccuname,$ccdomain,$formname,$crstype,$permission) = @_; + my $currentauth=&Apache::lonnet::queryauthenticate($ccuname,$ccdomain); + my $outcome; + 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" + ); + # Check for a bad authentication type + if ($currentauth !~ /^(krb4|krb5|unix|internal|localauth):/) { + # bad authentication scheme + if (&Apache::lonnet::allowed('mau',$ccdomain)) { + &initialize_authen_forms($ccdomain,$formname); + + my $choices = &Apache::lonuserutils::set_login($ccdomain,$authformkrb,$authformint,$authformloc); + $outcome = < +// -ERROR: -This user has an unrecognized authentication scheme ($currentauth). -Please specify login data below. -

Login Data

-

$generalrule

-

$authformkrb

-

$authformint

-

$authformfsys

-

$authformloc

+$lt{'err'}: +$lt{'uuas'} ($currentauth). $lt{'sldb'}. +

$lt{'ld'}

+$choices ENDBADAUTH - } else { - # This user is not allowed to modify the users - # authentication scheme, so just notify them of the problem - $r->print(< - - ERROR: -This user has an unrecognized authentication scheme ($currentauth). -Please alert a domain coordinator of this situation. -
+ } 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 + $outcome = + ''."\n". + '

'.$lt{'ld'}.'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(). + ''.$authformnop; + if (($can_modify) && (&Apache::lonnet::allowed('mau',$ccdomain))) { + $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"; } - } else { # Authentication type is valid - my $authformcurrent=''; - my $authform_other=''; - 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=< - -* * * WARNING * * * -* * * WARNING * * * - -$authformcurrent -Changing this value will overwrite existing authentication for the user; you should notify the user of this change. - -ENDCURRENTAUTH - if (&Apache::lonnet::allowed('mau',$ENV{'request.role.domain'})) { - # Current user has login modification privileges - $r->print(< - -

Change Current Login Data

-

$generalrule

-

$authformnop

-

$authformcurrent

-

Enter New Login Data

-$authform_other -ENDOTHERAUTHS +ENDJS + + $outcome .= '

'.$lt{'ld'}.'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(). + ''.&mt('Internally authenticated').'
'.&mt("Change user's password?"). + ''.(' 'x2). + ''. + ''. + &Apache::loncommon::end_data_table_row(). + &Apache::loncommon::end_data_table(); } - } ## End of "check for bad authentication type" logic - } ## End of new user/old user logic - $r->print('

Add Roles

'); -# -# Co-Author -# - if (&Apache::lonnet::allowed('cca',$ENV{'request.role.domain'})) { - my $cuname=$ENV{'user.name'}; - my $cudom=$ENV{'request.role.domain'}; - $r->print(<Construction Space - - - - - - - - - -
ActivateRoleExtentStartEnd
Co-Author$cudom\_$cuname -Set Start Date -Set End Date
-ENDCOAUTH + if (&Apache::lonnet::allowed('udp',$ccdomain)) { + # Current user has rights to view domain preferences for user's domain + my $result; + if ($currentauth =~ /^krb(4|5):([^:]*)$/) { + my ($krbver,$krbrealm) = ($1,$2); + if ($krbrealm eq '') { + $result = &mt('Currently Kerberos authenticated, Version [_1].',$krbver); + } else { + $result = &mt('Currently Kerberos authenticated with domain [_1] Version [_2].', + $krbrealm,$krbver); + } + } elsif ($currentauth =~ /^internal:/) { + $result = &mt('Currently internally authenticated.'); + } elsif ($currentauth =~ /^localauth:/) { + $result = &mt('Currently using local (institutional) authentication.'); + } elsif ($currentauth =~ /^unix:/) { + $result = &mt('Currently Filesystem Authenticated.'); + } + $outcome = '

'.$lt{'ld'}.'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_row(). + ''.$result.''. + &Apache::loncommon::end_data_table_row()."\n". + &Apache::loncommon::end_data_table(); + } elsif (&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; + } } -# -# Domain level -# - $r->print('

Domain Level

'. - ''. - ''); - foreach ( sort( keys(%incdomains))) { - my $thisdomain=$_; - foreach ('dc','li','dg','au') { - if (&Apache::lonnet::allowed('c'.$_,$thisdomain)) { - my $plrole=&Apache::lonnet::plaintext($_); - $r->print(< - - - - - - -ENDDROW + if ($show_override_msg) { + $authformcurrent = '
ActivateRoleExtentStartEnd
$plrole$thisdomain -Set Start Date -Set End Date
'."\n". + ''. + ''. + '
'.$authformcurrent. + '
   '.&mt('Currently in use').''. + &mt('will override current values'). + '
'; + } + return ($authformcurrent,$show_override_msg,@authform_others); +} + +sub personal_data_display { + my ($ccuname,$ccdomain,$newuser,$context,$inst_results,$rolesarray,$now, + $captchaform,$emailusername,$usertype,$usernameset,$condition,$excluded,$showsubmit) = @_; + my ($output,%userenv,%canmodify,%canmodify_status); + my @userinfo = ('firstname','middlename','lastname','generation', + 'permanentemail','id'); + my $rowcount = 0; + my $editable = 0; + my %textboxsize = ( + firstname => '15', + middlename => '15', + lastname => '15', + generation => '5', + permanentemail => '25', + id => '15', + ); + + 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", + 'email' => 'E-mail address', + 'valid' => 'Validation', + 'username' => 'Username', + ); + + %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') { + if ($newuser eq 'email') { + if (ref($emailusername) eq 'HASH') { + if (ref($emailusername->{$usertype}) eq 'HASH') { + my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info(); + @userinfo = (); + if ((ref($infofields) eq 'ARRAY') && (ref($infotitles) eq 'HASH')) { + foreach my $field (@{$infofields}) { + if ($emailusername->{$usertype}->{$field}) { + push(@userinfo,$field); + $canmodify{$field} = 1; + unless ($textboxsize{$field}) { + $textboxsize{$field} = 25; + } + unless ($lt{$field}) { + $lt{$field} = $infotitles->{$field}; + } + if ($emailusername->{$usertype}->{$field} eq 'required') { + $lt{$field} .= '*'; + } + } + } + } + } } - } + } else { + %canmodify = &selfcreate_canmodify($context,$ccdomain,\@userinfo, + $inst_results,$rolesarray); + } + } + + my $genhelp=&Apache::loncommon::help_open_topic('Generation'); + $output = '

'.$lt{'pd'}.'

'. + &Apache::lonhtmlcommon::start_pick_box(); + if (($context eq 'selfcreate') && ($newuser eq 'email')) { + my $size = 25; + if ($condition) { + if ($condition =~ /^\@[^\@]+$/) { + $size = 10; + } else { + undef($condition); + } + } + if ($excluded) { + unless ($excluded =~ /^\@[^\@]+$/) { + undef($condition); + } + } + $output .= &Apache::lonhtmlcommon::row_title($lt{'email'}.'*',undef, + 'LC_oddrow_value')."\n". + ''; + if ($condition) { + $output .= $condition; + } elsif ($excluded) { + $output .= '
'.&mt('You must use an e-mail address that does not end with [_1]', + $excluded).''; + } + if ($usernameset eq 'first') { + $output .= '
'; + if ($condition) { + $output .= &mt('Your username in LON-CAPA will be the part of your e-mail address before [_1]', + $condition); + } else { + $output .= &mt('Your username in LON-CAPA will be the part of your e-mail address before the @'); + } + $output .= ''; + } + $rowcount ++; + $output .= &Apache::lonhtmlcommon::row_closure(1); + my $upassone = ''; + my $upasstwo = ''; + $output .= &Apache::lonhtmlcommon::row_title(&mt('Password').'*', + 'LC_pick_box_title', + 'LC_oddrow_value')."\n". + $upassone."\n". + &Apache::lonhtmlcommon::row_closure(1)."\n". + &Apache::lonhtmlcommon::row_title(&mt('Confirm password').'*', + 'LC_pick_box_title', + 'LC_oddrow_value')."\n". + $upasstwo. + &Apache::lonhtmlcommon::row_closure()."\n"; + if ($usernameset eq 'free') { + my $onclick = "toggleUsernameDisp(this,'selfcreateusername');"; + $output .= &Apache::lonhtmlcommon::row_title($lt{'username'},undef,'LC_oddrow_value')."\n". + ''.&mt('Use e-mail address: '). + ''.(' 'x2). + ''."\n". + ''."\n".&Apache::lonhtmlcommon::row_closure(1); + $rowcount ++; + } + } + 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 ($canmodify{$item}) { + if ($newuser eq 'email') { + $row .= ''; + } else { + $row .= ''; + } + $editable ++; + } else { + $hiderow = 1; + } + } else { + $row .= ''; + } + } + } else { + if ($canmodify{$item}) { + $row .= ''; + if (($item eq 'id') && (!$newuser)) { + $row .= '
'.&Apache::lonuserutils::forceid_change($context); + } + } else { + $row .= $userenv{$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('Affiliations'),undef,'LC_oddrow_value')."\n". + $shown.&Apache::lonhtmlcommon::row_closure(1); + if ($context eq 'selfcreate') { + $rowcount ++; + } + $output .= $row; + } + } + } + } + if (($context eq 'selfcreate') && ($newuser eq 'email')) { + if ($captchaform) { + $output .= &Apache::lonhtmlcommon::row_title($lt{'valid'}.'*', + 'LC_pick_box_title')."\n". + $captchaform."\n".'

'. + &Apache::lonhtmlcommon::row_closure(1); + $rowcount ++; + } + if ($showsubmit) { + my $submit_text = &mt('Create account'); + $output .= &Apache::lonhtmlcommon::row_title()."\n". + '
'; + if ($usertype ne '') { + $output .= ''. + &Apache::lonhtmlcommon::row_closure(1); + } + } + } + $output .= &Apache::lonhtmlcommon::end_pick_box(); + if (wantarray) { + if ($context eq 'selfcreate') { + return($output,$rowcount,$editable); + } else { + return $output; + } + } else { + return $output; } - $r->print(''); -# -# Course level -# - $r->print(&course_level_table(%inccourses)); - $r->print("
\n"); - $r->print(""); +} + +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 $uhome=&Apache::lonnet::homeserver($ENV{'form.ccuname'}, - $ENV{'form.ccdomain'}); + my ($r,$context,$crstype,$brcrum,$showcredits,$permission) = @_; + my $uhome=&Apache::lonnet::homeserver($env{'form.ccuname'}, + $env{'form.ccdomain'}); # Error messages - my $error = 'Error:'; - my $end = ''; - # Print header - $r->print(< - -The LearningOnline Network with CAPA - - - -ENDTHREEHEAD + 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'; + } + my $newuser = 0; + my ($jsback,$elements) = &crumb_utilities(); + my $jscript = ''."\n"; + my %breadcrumb_text = &singleuser_breadcrumb($crstype,$context,$env{'form.ccdomain'}); + 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'; + } elsif ($context eq 'author') { + $helpitem = 'Author_Change_Privileges'; + } elsif ($context eq 'domain') { + $helpitem = 'Domain_Change_Privileges'; + } + 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.'No login name specified.'.$end); + if (! $env{'form.ccuname'} ) { + $r->print($error.&mt('No login name specified').'.'.$end.$rtnlink); return; } - if ( $ENV{'form.ccuname'} =~/\W/) { - $r->print($error.'Invalid login name. '. - '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.'No domain specified.'.$end); + if (! $env{'form.ccdomain'} ) { + $r->print($error.&mt('No domain specified').'.'.$end.$rtnlink); return; } - if ( $ENV{'form.ccdomain'} =~/\W/) { - $r->print($error.'Invalid domain name. '. - '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 (! exists($ENV{'form.makeuser'})) { + 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') { - $r->print($error.'Unable to determine home server for '. - $ENV{'form.ccuname'}.' in domain '. - $ENV{'form.ccdomain'}.'.'); + $r->print( + $error + .'

' + .&mt('Unable to determine home server for [_1] in domain [_2].', + '"'.$env{'form.ccuname'}.'"','"'.$env{'form.ccdomain'}.'"') + .'

'); return; } } # Determine authentication method and password for the user being modified my $amode=''; my $genpwd=''; - if ($ENV{'form.login'} eq 'krb') { + if ($env{'form.login'} eq 'krb') { $amode='krb'; - $amode.=$ENV{'form.krbver'}; - $genpwd=$ENV{'form.krbarg'}; - } elsif ($ENV{'form.login'} eq 'int') { + $amode.=$env{'form.krbver'}; + $genpwd=$env{'form.krbarg'}; + } elsif ($env{'form.login'} eq 'int') { $amode='internal'; - $genpwd=$ENV{'form.intarg'}; - } elsif ($ENV{'form.login'} eq 'fsys') { + $genpwd=$env{'form.intarg'}; + } elsif ($env{'form.login'} eq 'fsys') { $amode='unix'; - $genpwd=$ENV{'form.fsysarg'}; - } elsif ($ENV{'form.login'} eq 'loc') { + $genpwd=$env{'form.fsysarg'}; + } elsif ($env{'form.login'} eq 'loc') { $amode='localauth'; - $genpwd=$ENV{'form.locarg'}; + $genpwd=$env{'form.locarg'}; $genpwd=" " if (!$genpwd); - } elsif (($ENV{'form.login'} eq 'nochange') || - ($ENV{'form.login'} eq '' )) { + } elsif (($env{'form.login'} eq 'nochange') || + ($env{'form.login'} eq '' )) { # There is no need to tell the user we did not change what they # did not ask us to change. # If they are creating a new user but have not specified login # information this will be caught below. } else { - $r->print($error.'Invalid login mode or password'.$end); - return; + $r->print($error.&mt('Invalid login mode or password').$end.$rtnlink); + return; } - if ($ENV{'form.makeuser'}) { - # Create a new user - $r->print(<Create User -

Creating user "$ENV{'form.ccuname'}" in domain "$ENV{'form.ccdomain'}"

-ENDNEWUSERHEAD + + $r->print('

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

'); + my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($r,2); + + my (%alerts,%rulematch,%inst_results,%curr_rules); + my @userinfo = ('firstname','middlename','lastname','generation','permanentemail','id'); + my @usertools = ('aboutme','blog','webdav','portfolio','timezone'); + my @requestcourses = ('official','unofficial','community','textbook'); + my @requestauthor = ('requestauthor'); + 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'}) { + $r->print('

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

'); # Check for the authentication mode and password if (! $amode || ! $genpwd) { - $r->print($error.'Invalid login mode or password'.$end); + $r->print($error.&mt('Invalid login mode or password').$end.$rtnlink); return; } # Determine desired host - my $desiredhost = $ENV{'form.hserver'}; + my $desiredhost = $env{'form.hserver'}; 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.'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; + } + } + } + } + &Apache::lonhtmlcommon::Increment_PrgWin($r, \%prog_state); # 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 - ); - $r->print('Generating user: '.$result); - my $home = &Apache::lonnet::homeserver($ENV{'form.ccuname'}, - $ENV{'form.ccdomain'}); - $r->print('
Home server: '.$home.' '. - $Apache::lonnet::libserv{$home}); - } elsif (($ENV{'form.login'} ne 'nochange') && - ($ENV{'form.login'} ne '' )) { + ($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); + $uhome = &Apache::lonnet::homeserver($env{'form.ccuname'}, + $env{'form.ccdomain'}); + my (%changeHash,%newcustom,%changed,%changedinfo); + if ($uhome ne 'no_host') { + if ($context eq 'domain') { + foreach my $name ('portfolio','author') { + if ($env{'form.custom_'.$name.'quota'} == 1) { + if ($env{'form.'.$name.'quota'} eq '') { + $newcustom{$name.'quota'} = 0; + } else { + $newcustom{$name.'quota'} = $env{'form.'.$name.'quota'}; + $newcustom{$name.'quota'} =~ s/[^\d\.]//g; + } + if ("a_admin($newcustom{$name.'quota'},\%changeHash,$name)) { + $changed{$name.'quota'} = 1; + } + } + } + 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} .= '='; + $env{'form.crsreq_'.$item.'_limit'} =~ s/\D+//g; + if ($env{'form.crsreq_'.$item.'_limit'}) { + $newcustom{$item} .= $env{'form.crsreq_'.$item.'_limit'}; + } + } + $changed{$item} = &tool_admin($item,$newcustom{$item}, + \%changeHash,'requestcourses'); + } + } + if ($env{'form.customrequestauthor'} == 1) { + $newcustom{'requestauthor'} = $env{'form.requestauthor'}; + $changed{'requestauthor'} = &tool_admin('requestauthor', + $newcustom{'requestauthor'}, + \%changeHash,'requestauthor'); + } + } + 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 - $r->print(<Change User Privileges -

User "$ENV{'form.ccuname'}" in domain "$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 - if (&Apache::lonnet::allowed('mau',$ENV{'form.ccdomain'})) { + # Only allow authentication modification if the person has authority + if (&Apache::lonnet::allowed('mau',$env{'form.ccdomain'})) { $r->print('Modifying authentication: '. &Apache::lonnet::modifyuserauth( - $ENV{'form.ccdomain'},$ENV{'form.ccuname'}, + $env{'form.ccdomain'},$env{'form.ccuname'}, $amode,$genpwd)); - $r->print('
Home server: '.&Apache::lonnet::homeserver - ($ENV{'form.ccuname'},$ENV{'form.ccdomain'})); + $r->print('
'.&mt('Home Server').': '.&Apache::lonnet::homeserver + ($env{'form.ccuname'},$env{'form.ccdomain'})); } else { # Okay, this is a non-fatal error. - $r->print($error.'You do not have the authority to modify '. - 'this users authentification information.'); + $r->print($error.&mt('You do not have privileges to modify the authentication configuration for this user.').$end); } + } elsif (($env{'form.intarg'} ne '') && + (&Apache::lonnet::queryauthenticate($env{'form.ccuname'},$env{'form.ccdomain'}) =~ /^internal:/) && + (&Apache::lonuserutils::can_change_internalpass($env{'form.ccuname'},$env{'form.ccdomain'},$crstype,$permission))) { + $r->print('Modifying authentication: '. + &Apache::lonnet::modifyuserauth( + $env{'form.ccdomain'},$env{'form.ccuname'}, + 'internal',$env{'form.intarg'})); } + $r->rflush(); # Finish display of header before time consuming actions start + &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state); ## - if (! $ENV{'form.makeuser'} ) { + my (@userroles,%userupdate,$cnum,$cdom,$defaultcredits,%namechanged); + if ($context eq 'course') { + ($cnum,$cdom) = + &Apache::lonuserutils::get_course_identity(); + $crstype = &Apache::loncommon::course_type($cdom.'_'.$cnum); + if ($showcredits) { + $defaultcredits = &Apache::lonuserutils::get_defaultcredits($cdom,$cnum); + } + } + if (! $env{'form.makeuser'} ) { # Check for need to change my %userenv = &Apache::lonnet::get - ('environment',['firstname','middlename','lastname','generation'], - $ENV{'form.ccdomain'},$ENV{'form.ccuname'}); + ('environment',['firstname','middlename','lastname','generation', + 'id','permanentemail','portfolioquota','authorquota','inststatus', + 'tools.aboutme','tools.blog','tools.webdav', + 'tools.portfolio','tools.timezone', + 'requestcourses.official','requestcourses.unofficial', + 'requestcourses.community','requestcourses.textbook', + 'reqcrsotherdom.official','reqcrsotherdom.unofficial', + 'reqcrsotherdom.community','reqcrsotherdom.textbook', + 'requestauthor'], + $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 ('firstname','middlename','lastname','generation') { + 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'}; + } + 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 { + # 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'.$_} =~ s/(\s+$|^\s+)//g; + $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}; + } } - 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'} )) { - # Make the change - my %changeHash; - $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 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,%oldquota,%newquota,%olddefquota,%newdefquota, + $oldinststatus,$newinststatus,%oldisdefault,%newisdefault,%oldsettings, + %oldsettingstext,%newsettings,%newsettingstext,@disporder, + %oldsettingstatus,%newsettingstatus); + @disporder = ('inststatus'); + if ($env{'request.role.domain'} eq $env{'form.ccdomain'}) { + push(@disporder,'requestcourses','requestauthor'); + } else { + push(@disporder,'reqcrsotherdom'); + } + push(@disporder,('quota','tools')); + $oldinststatus = $userenv{'inststatus'}; + foreach my $name ('portfolio','author') { + ($olddefquota{$name},$oldsettingstatus{$name}) = + &Apache::loncommon::default_quota($env{'form.ccdomain'},$oldinststatus,$name); + ($newdefquota{$name},$newsettingstatus{$name}) = ($olddefquota{$name},$oldsettingstatus{$name}); + } + 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; + } + if (&Apache::lonnet::allowed('cau',$env{'form.ccdomain'})) { + $canshow{'requestauthor'} = 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; + foreach my $name ('portfolio','author') { + ($newdefquota{$name},$newsettingstatus{$name}) = + &Apache::loncommon::default_quota($env{'form.ccdomain'},$newinststatus,$name); + } + } + 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'}; + foreach my $name ('portfolio','author') { + ($newdefquota{$name},$newsettingstatus{$name}) = + &Apache::loncommon::default_quota($env{'form.ccdomain'},$newinststatus,$name); + } + } + } + } elsif ($context ne 'selfcreate') { + $canshow{'inststatus'} = 1; + $newsettings{'inststatus'} = $oldsettings{'inststatus'}; + } + foreach my $name ('portfolio','author') { + $changeHash{$name.'quota'} = $userenv{$name.'quota'}; + } + if ($context eq 'domain') { + foreach my $name ('portfolio','author') { + if ($userenv{$name.'quota'} ne '') { + $oldquota{$name} = $userenv{$name.'quota'}; + if ($env{'form.custom_'.$name.'quota'} == 1) { + if ($env{'form.'.$name.'quota'} eq '') { + $newquota{$name} = 0; + } else { + $newquota{$name} = $env{'form.'.$name.'quota'}; + $newquota{$name} =~ s/[^\d\.]//g; + } + if ($newquota{$name} != $oldquota{$name}) { + if ("a_admin($newquota{$name},\%changeHash,$name)) { + $changed{$name.'quota'} = 1; + } + } + } else { + if ("a_admin('',\%changeHash,$name)) { + $changed{$name.'quota'} = 1; + $newquota{$name} = $newdefquota{$name}; + $newisdefault{$name} = 1; + } + } + } else { + $oldisdefault{$name} = 1; + $oldquota{$name} = $olddefquota{$name}; + if ($env{'form.custom_'.$name.'quota'} == 1) { + if ($env{'form.'.$name.'quota'} eq '') { + $newquota{$name} = 0; + } else { + $newquota{$name} = $env{'form.'.$name.'quota'}; + $newquota{$name} =~ s/[^\d\.]//g; + } + if ("a_admin($newquota{$name},\%changeHash,$name)) { + $changed{$name.'quota'} = 1; + } + } else { + $newquota{$name} = $newdefquota{$name}; + $newisdefault{$name} = 1; + } + } + if ($oldisdefault{$name}) { + $oldsettingstext{'quota'}{$name} = &get_defaultquota_text($oldsettingstatus{$name}); + } else { + $oldsettingstext{'quota'}{$name} = &mt('custom quota: [_1] MB',$oldquota{$name}); + } + if ($newisdefault{$name}) { + $newsettingstext{'quota'}{$name} = &get_defaultquota_text($newsettingstatus{$name}); + } else { + $newsettingstext{'quota'}{$name} = &mt('custom quota: [_1] MB',$newquota{$name}); + } + } + &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); + &tool_changes('requestauthor',\@requestauthor,\%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; + } + } + foreach my $name ('portfolio','author') { + $oldsettings{'quota'}{$name} = &mt('[_1] MB',$oldquota{$name}); + $newsettings{'quota'}{$name} = &mt('[_1] MB',$newquota{$name}); + } + 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') || ($key eq 'textbook')) { + $newenvhash{'environment.requestcourses.'.$key} = + $changeHash{'requestcourses.'.$key}; + if ($changeHash{'requestcourses.'.$key}) { + $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 eq 'requestauthor') { + $newenvhash{'environment.'.$key} = $changeHash{$key}; + if ($changeHash{$key}) { + $newenvhash{'environment.canrequest.author'} = 1; + } else { + $newenvhash{'environment.canrequest.author'} = + &Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'}, + $key,'reload','requestauthor'); + } + } 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 ($changed{'aboutme'}) { + &Apache::loncommon::devalidate_aboutme_cache($env{'form.ccuname'}, + $env{'form.ccdomain'}); + } + } + } + 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 - $r->print(<<"END"); - - - - - - - - - - - - - - - - - -
User Information Changed
 firstmiddlelastgeneration
Previous$userenv{'firstname'} $userenv{'middlename'} $userenv{'lastname'} $userenv{'generation'}
Changed To$ENV{'form.cfirstname'} $ENV{'form.cmiddlename'} $ENV{'form.clastname'} $ENV{'form.cgeneration'}
-END + &display_userinfo($r,1,\@disporder,\%canshow,\@requestcourses, + \@usertools,\@requestauthor,\%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("

Unable to successfully change environment for ". - $ENV{'form.ccuname'}." in domain ". - $ENV{'form.ccdomain'}."

"); - } - } else { # End of if ($ENV ... ) logic - # They did not want to change the users name but we can - # still tell them what the name is - $r->print(<<"END"); -

User "$ENV{'form.ccuname'}" in domain "$ENV{'form.ccdomain'}"

-

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

-

Generation: $userenv{'generation'}

-END + $r->print( + '

' + .&mt('Unable to successfully change environment for [_1] in domain [_2].', + '"'.$env{'form.ccuname'}.'"', + '"'.$env{'form.ccdomain'}.'"') + .'

'); + } + } 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,\@requestauthor,\%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 = 'course'; + } elsif ($context eq 'author') { + $contextname = '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 $contextname roles:")); + } else { + $r->print(&mt("You do not have the authority to change these fields given the user's current set of active/future $contextname roles:")); + } + 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) + .''); } - ## + &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); + if ($env{'form.action'} eq 'singlestudent') { + &enroll_single_student($r,$uhome,$amode,$genpwd,$now,$newuser,$context, + $crstype,$showcredits,$defaultcredits); + my $linktext = ($crstype eq 'Community' ? + &mt('Enroll Another Member') : &mt('Enroll Another Student')); + $r->print( + &Apache::lonhtmlcommon::actionbox([ + '' + .($crstype eq 'Community' ? + &mt('Enroll Another Member') : &mt('Enroll Another Student')) + .''])); + } else { + my @rolechanges = &update_roles($r,$context,$showcredits); + 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('
'.&Apache::lonhtmlcommon::actionbox(['' + .&mt('Modify this user: [_1]',''.$env{'form.ccuname'}.':'.$env{'form.ccdomain'}.' ('.$userinfo.')').'', + ''.&mt('Create/Modify Another User').''])); + } + } +} + +sub display_userinfo { + my ($r,$changed,$order,$canshow,$requestcourses,$usertools,$requestauthor, + $userenv,$changedhash,$namechangedhash,$oldsetting,$oldsettingtext, + $newsetting,$newsettingtext) = @_; + return unless (ref($order) eq 'ARRAY' && + ref($canshow) eq 'HASH' && + ref($requestcourses) eq 'ARRAY' && + ref($requestauthor) 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', + 'uic' => 'User Information Changed', + 'firstname' => 'First Name', + 'middlename' => 'Middle Name', + 'lastname' => 'Last Name', + 'generation' => 'Generation', + 'id' => 'Student/Employee ID', + 'permanentemail' => 'Permanent e-mail address', + 'portfolioquota' => 'Disk space allocated to portfolio files', + 'authorquota' => 'Disk space allocated to Authoring Space', + 'blog' => 'Blog Availability', + 'webdav' => 'WebDAV Availability', + 'aboutme' => 'Personal Information Page Availability', + 'portfolio' => 'Portfolio Availability', + 'timezone' => 'Can set own Time Zone', + 'official' => 'Can Request Official Courses', + 'unofficial' => 'Can Request Unofficial Courses', + 'community' => 'Can Request Communities', + 'textbook' => 'Can Request Textbook Courses', + 'requestauthor' => 'Can Request Author Role', + 'inststatus' => "Affiliation", + 'prvs' => 'Previous Value:', + 'chto' => 'Changed To:' + ); + if ($changed) { + $r->print('

'.$lt{'uic'}.'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row()); + $r->print(" \n"); + $r->print(''.$lt{'prvs'}.''); + $r->print(''.$lt{'chto'}.''); + $r->print(&Apache::loncommon::end_data_table_header_row()); + my @userinfo = ('firstname','middlename','lastname','generation','permanentemail','id'); + + foreach my $item (@userinfo) { + my $value = $env{'form.c'.$item}; + #show changes only: + unless ($value eq $userenv->{$item}){ + $r->print(&Apache::loncommon::start_data_table_row()); + $r->print("$lt{$item}\n"); + $r->print("".$userenv->{$item}."\n"); + $r->print("$value \n"); + $r->print(&Apache::loncommon::end_data_table_row()); + } + } + foreach my $entry (@{$order}) { + if ($canshow->{$entry}) { + if (($entry eq 'requestcourses') || ($entry eq 'reqcrsotherdom') || ($entry eq 'requestauthor')) { + my @items; + if ($entry eq 'requestauthor') { + @items = ($entry); + } else { + @items = @{$requestcourses}; + } + foreach my $item (@items) { + if (($newsetting->{$item} ne $oldsetting->{$item}) || + ($newsettingtext->{$item} ne $oldsettingtext->{$item})) { + $r->print(&Apache::loncommon::start_data_table_row()."\n"); + $r->print("$lt{$item}\n"); + $r->print("".$oldsetting->{$item}); + if ($oldsettingtext->{$item}) { + if ($oldsetting->{$item}) { + $r->print(' -- '); + } + $r->print($oldsettingtext->{$item}); + } + $r->print("\n"); + $r->print("".$newsetting->{$item}); + if ($newsettingtext->{$item}) { + if ($newsetting->{$item}) { + $r->print(' -- '); + } + $r->print($newsettingtext->{$item}); + } + $r->print("\n"); + $r->print(&Apache::loncommon::end_data_table_row()."\n"); + } + } + } elsif ($entry eq 'tools') { + foreach my $item (@{$usertools}) { + if ($newsetting->{$item} ne $oldsetting->{$item}) { + $r->print(&Apache::loncommon::start_data_table_row()."\n"); + $r->print("$lt{$item}\n"); + $r->print("".$oldsetting->{$item}.' '.$oldsettingtext->{$item}."\n"); + $r->print("".$newsetting->{$item}.' '.$newsettingtext->{$item}."\n"); + $r->print(&Apache::loncommon::end_data_table_row()."\n"); + } + } + } elsif ($entry eq 'quota') { + if ((ref($oldsetting->{$entry}) eq 'HASH') && (ref($oldsettingtext->{$entry}) eq 'HASH') && + (ref($newsetting->{$entry}) eq 'HASH') && (ref($newsettingtext->{$entry}) eq 'HASH')) { + foreach my $name ('portfolio','author') { + if ($newsetting->{$entry}->{$name} ne $oldsetting->{$entry}->{$name}) { + $r->print(&Apache::loncommon::start_data_table_row()."\n"); + $r->print("$lt{$name.$entry}\n"); + $r->print("".$oldsettingtext->{$entry}->{$name}."\n"); + $r->print("".$newsettingtext->{$entry}->{$name}."\n"); + $r->print(&Apache::loncommon::end_data_table_row()."\n"); + } + } + } + } else { + if ($newsetting->{$entry} ne $oldsetting->{$entry}) { + $r->print(&Apache::loncommon::start_data_table_row()."\n"); + $r->print("$lt{$entry}\n"); + $r->print("".$oldsetting->{$entry}.' '.$oldsettingtext->{$entry}."\n"); + $r->print("".$newsetting->{$entry}.' '.$newsettingtext->{$entry}."\n"); + $r->print(&Apache::loncommon::end_data_table_row()."\n"); + } + } + } + } + $r->print(&Apache::loncommon::end_data_table().'
'); + } else { + $r->print('

'.$lt{'ui'}.'

'. + '

'.&mt('No changes made to user information').'

'); + } + 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; + } + my %reqdisplay = &requestchange_display(); + if ($context eq 'reqcrsotherdom') { + my @options = ('approval','validate','autolimit'); + my $optregex = join('|',@options); + my $cdom = $env{'request.role.domain'}; + foreach my $tool (@{$usertools}) { + $oldaccesstext->{$tool} = &mt("availability set to 'off'"); + $newaccesstext->{$tool} = $oldaccesstext->{$tool}; + $changeHash->{$context.'.'.$tool} = $userenv->{$context.'.'.$tool}; + my ($newop,$limit); + if ($env{'form.'.$context.'_'.$tool}) { + $newop = $env{'form.'.$context.'_'.$tool}; + if ($newop eq 'autolimit') { + $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}) { + if ($newop =~ /^autolimit/) { + if ($limit) { + $newaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$limit); + } else { + $newaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } + } else { + $newaccesstext->{$tool} = $reqdisplay{$newop}; + } + } 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*)$/) { + my $oldop = $1; + if ($oldop =~ /^autolimit=(\d*)/) { + my $limit = $1; + if ($limit) { + $oldaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$limit); + } else { + $oldaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } + } else { + $oldaccesstext->{$tool} = $reqdisplay{$oldop}; + } + 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('available with automatic approval, up to limit of [quant,_1,request] per user',$limit); + } else { + $newaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } + } else { + $newaccesstext->{$tool} = $reqdisplay{$env{'form.'.$context.'_'.$tool}}; + } + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } + } + } + } + return; + } + foreach my $tool (@{$usertools}) { + my ($newval,$limit,$envkey); + $envkey = $context.'.'.$tool; + if ($context eq 'requestcourses') { + $newval = $env{'form.crsreq_'.$tool}; + if ($newval eq 'autolimit') { + $limit = $env{'form.crsreq_'.$tool.'_limit'}; + $limit =~ s/\D+//g; + $newval .= '='.$limit; + } + } elsif ($context eq 'requestauthor') { + $newval = $env{'form.'.$context}; + $envkey = $context; + } else { + $newval = $env{'form.'.$context.'_'.$tool}; + } + if ($userenv->{$envkey} ne '') { + $oldaccess->{$tool} = &mt('custom'); + if (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + if ($userenv->{$envkey} =~ /^autolimit=(\d*)$/) { + my $currlimit = $1; + if ($currlimit eq '') { + $oldaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } else { + $oldaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$currlimit); + } + } elsif ($userenv->{$envkey}) { + $oldaccesstext->{$tool} = $reqdisplay{$userenv->{$envkey}}; + } else { + $oldaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } else { + if ($userenv->{$envkey}) { + $oldaccesstext->{$tool} = &mt("availability set to 'on'"); + } else { + $oldaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } + $changeHash->{$envkey} = $userenv->{$envkey}; + if ($env{'form.custom'.$tool} == 1) { + if ($newval ne $userenv->{$envkey}) { + $changed->{$tool} = &tool_admin($tool,$newval,$changeHash, + $context); + if ($changed->{$tool}) { + $newaccess->{$tool} = &mt('custom'); + if (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + if ($newval =~ /^autolimit/) { + if ($limit) { + $newaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$limit); + } else { + $newaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } + } elsif ($newval) { + $newaccesstext->{$tool} = $reqdisplay{$newval}; + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } else { + if ($newval) { + $newaccesstext->{$tool} = &mt("availability set to 'on'"); + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } + } else { + $newaccess->{$tool} = $oldaccess->{$tool}; + if (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + if ($newval =~ /^autolimit/) { + if ($limit) { + $newaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$limit); + } else { + $newaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } + } elsif ($newval) { + $newaccesstext->{$tool} = $reqdisplay{$newval}; + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } else { + 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 (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + if ($newval =~ /^autolimit/) { + if ($limit) { + $newaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$limit); + } else { + $newaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } + } elsif ($newval) { + $newaccesstext->{$tool} = $reqdisplay{$newval}; + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } else { + 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 (($context eq 'requestcourses') || ($context eq 'requestauthor')) { + if ($newval =~ /^autolimit/) { + if ($limit) { + $newaccesstext->{$tool} = &mt('available with automatic approval, up to limit of [quant,_1,request] per user',$limit); + } else { + $newaccesstext->{$tool} = &mt('available with automatic approval (unlimited)'); + } + } elsif ($newval) { + $newaccesstext->{$tool} = $reqdisplay{$newval}; + } else { + $newaccesstext->{$tool} = &mt("availability set to 'off'"); + } + } else { + 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,$showcredits) = @_; my $now=time; - $r->print('

Modifying Roles

'); - foreach (keys (%ENV)) { - next if (! $ENV{$_}); + 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 ($_=~/^form\.rev/) { - if ($_=~/^form\.rev\:([^\_]+)\_([^\_]+)$/) { - $r->print('Revoking '.$2.' in '.$1.': '. - &Apache::lonnet::assignrole($ENV{'form.ccdomain'}, - $ENV{'form.ccuname'},$1,$2,$now).'
'); - if ($2 eq 'st') { - $1=~/^\/(\w+)\/(\w+)/; - my $cid=$1.'_'.$2; - $r->print('Drop from classlist: '. - &Apache::lonnet::critical('put:'. - $ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}.':classlist:'. - &Apache::lonnet::escape($ENV{'form.ccuname'}.':'. - $ENV{'form.ccdomain'}).'='. - &Apache::lonnet::escape($now.':'), - $ENV{'course.'.$cid.'.home'}).'
'); + if ($key=~/^form\.rev/) { + if ($key=~/^form\.rev\:([^\_]+)\_([^\_\.]+)$/) { +# Revoke standard role + my ($scope,$role) = ($1,$2); + my $result = + &Apache::lonnet::revokerole($env{'form.ccdomain'}, + $env{'form.ccuname'}, + $scope,$role,'','',$context); + $r->print(&Apache::lonhtmlcommon::confirm_success( + &mt('Revoking [_1] in [_2]', + &Apache::lonnet::plaintext($role), + &Apache::loncommon::show_role_extent($scope,$context,$role)), + $result ne "ok").'
'); + if ($result ne "ok") { + $r->print(&mt('Error: [_1]',$result).'
'); + } + if ($role eq 'st') { + my $result = + &Apache::lonuserutils::classlist_drop($scope, + $env{'form.ccuname'},$env{'form.ccdomain'}, + $now); + $r->print(&Apache::lonhtmlcommon::confirm_success($result)); } - } - } elsif ($_=~/^form\.act/) { - if ($_=~/^form\.act\_([^\_]+)\_([^\_]+)\_([^\_]+)$/) { + 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 + my $result = &Apache::lonnet::revokecustomrole( + $env{'form.ccdomain'},$env{'form.ccuname'},$1,$2,$3,$4,'','',$context); + $r->print(&Apache::lonhtmlcommon::confirm_success( + &mt('Revoking custom role [_1] by [_2] in [_3]', + $4,$3.':'.$2,&Apache::loncommon::show_role_extent($1,$context,'cr')), + $result ne 'ok').'
'); + if ($result ne "ok") { + $r->print(&mt('Error: [_1]',$result).'
'); + } + if (!grep(/^cr$/,@rolechanges)) { + push(@rolechanges,'cr'); + } + } + } elsif ($key=~/^form\.del/) { + if ($key=~/^form\.del\:([^\_]+)\_([^\_\.]+)$/) { +# Delete standard role + my ($scope,$role) = ($1,$2); + my $result = + &Apache::lonnet::assignrole($env{'form.ccdomain'}, + $env{'form.ccuname'}, + $scope,$role,$now,0,1,'', + $context); + $r->print(&Apache::lonhtmlcommon::confirm_success( + &mt('Deleting [_1] in [_2]', + &Apache::lonnet::plaintext($role), + &Apache::loncommon::show_role_extent($scope,$context,$role)), + $result ne 'ok').'
'); + if ($result ne "ok") { + $r->print(&mt('Error: [_1]',$result).'
'); + } + + if ($role eq 'st') { + my $result = + &Apache::lonuserutils::classlist_drop($scope, + $env{'form.ccuname'},$env{'form.ccdomain'}, + $now); + $r->print(&Apache::lonhtmlcommon::confirm_success($result)); + } + if (!grep(/^\Q$role\E$/,@rolechanges)) { + push(@rolechanges,$role); + } + } + if ($key=~m{^form\.del\:([^_]+)_cr\.cr/($match_domain)/($match_username)/(\w+)$}) { + my ($url,$rdom,$rnam,$rolename) = ($1,$2,$3,$4); +# Delete custom role + my $result = + &Apache::lonnet::assigncustomrole($env{'form.ccdomain'}, + $env{'form.ccuname'},$url,$rdom,$rnam,$rolename,$now, + 0,1,$context); + $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('Deleting custom role [_1] by [_2] in [_3]', + $rolename,$rnam.':'.$rdom,&Apache::loncommon::show_role_extent($1,$context,'cr')), + $result ne "ok").'
'); + if ($result ne "ok") { + $r->print(&mt('Error: [_1]',$result).'
'); + } + + if (!grep(/^cr$/,@rolechanges)) { + push(@rolechanges,'cr'); + } + } + } elsif ($key=~/^form\.ren/) { + my $udom = $env{'form.ccdomain'}; + my $uname = $env{'form.ccuname'}; +# Re-enable standard role + if ($key=~/^form\.ren\:([^\_]+)\_([^\_\.]+)$/) { + my $url = $1; + my $role = $2; + my $logmsg; + my $output; + if ($role eq 'st') { + if ($url =~ m-^/($match_domain)/($match_courseid)/?(\w*)$-) { + my ($cdom,$cnum,$csec) = ($1,$2,$3); + my $credits; + if ($showcredits) { + my $defaultcredits = + &Apache::lonuserutils::get_defaultcredits($cdom,$cnum); + $credits = &get_user_credits($defaultcredits,$cdom,$cnum); + } + my $result = &Apache::loncommon::commit_studentrole(\$logmsg,$udom,$uname,$url,$role,$now,0,$cdom,$cnum,$csec,$context,$credits); + if (($result =~ /^error/) || ($result eq 'not_in_class') || ($result eq 'unknown_course') || ($result eq 'refused')) { + if ($result eq 'refused' && $logmsg) { + $output = $logmsg; + } else { + $output = &mt('Error: [_1]',$result)."\n"; + } + } else { + $output = &Apache::lonhtmlcommon::confirm_success(&mt('Assigning [_1] in [_2] starting [_3]', + &Apache::lonnet::plaintext($role), + &Apache::loncommon::show_role_extent($url,$context,'st'), + &Apache::lonlocal::locallocaltime($now))).'
'.$logmsg.'
'; + } + } + } else { + my $result=&Apache::lonnet::assignrole($env{'form.ccdomain'}, + $env{'form.ccuname'},$url,$role,0,$now,'','', + $context); + $output = &Apache::lonhtmlcommon::confirm_success(&mt('Re-enabling [_1] in [_2]', + &Apache::lonnet::plaintext($role), + &Apache::loncommon::show_role_extent($url,$context,$role)),$result ne "ok").'
'; + if ($result ne "ok") { + $output .= &mt('Error: [_1]',$result).'
'; + } + } + $r->print($output); + if (!grep(/^\Q$role\E$/,@rolechanges)) { + push(@rolechanges,$role); + } + } +# Re-enable custom role + 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,undef,$context); + $r->print(&Apache::lonhtmlcommon::confirm_success( + &mt('Re-enabling custom role [_1] by [_2] in [_3]', + $rolename,$rnam.':'.$rdom,&Apache::loncommon::show_role_extent($1,$context,'cr')), + $result ne "ok").'
'); + if ($result ne "ok") { + $r->print(&mt('Error: [_1]',$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\_($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; + my $full=$one.'_'.$two.'_cr_cr_'.$three.'_'.$four.'_'.$five; + + my $start = ( $env{'form.start_'.$full} ? + $env{'form.start_'.$full} : + $now ); + my $end = ( $env{'form.end_'.$full} ? + $env{'form.end_'.$full} : + 0 ); + + # split multiple sections + 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,$context)); + } else { + my %curr_groups = + &Apache::longroup::coursegroups($one,$two); + foreach my $sec (sort {$a cmp $b} keys(%sections)) { + if (($sec eq 'none') || ($sec eq 'all') || + exists($curr_groups{$sec})) { + $disallowed{$sec} = $url; + next; + } + my $securl = $url.'/'.$sec; + $r->print(&Apache::loncommon::commit_customrole($udom,$uname,$securl,$three,$four,$five,$start,$end,$context)); + } + } + 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 $start = ( $ENV{'form.start_'.$1.'_'.$2} ? - $ENV{'form.start_'.$1.'_'.$2} : + my ($one,$two,$three)=($1,$2,$3); + my $start = ( $env{'form.start_'.$one.'_'.$two.'_'.$three} ? + $env{'form.start_'.$one.'_'.$two.'_'.$three} : $now ); - my $end = ( $ENV{'form.end_'.$1.'_'.$2} ? - $ENV{'form.end_'.$1.'_'.$2} : + my $end = ( $env{'form.end_'.$one.'_'.$two.'_'.$three} ? + $env{'form.end_'.$one.'_'.$two.'_'.$three} : 0 ); - my $url='/'.$1.'/'.$2; - if ($ENV{'form.sec_'.$1.'_'.$2.'_'.$3}) { - $url.='/'.$ENV{'form.sec_'.$1.'_'.$2.'_'.$3}; - } - # Assign the role and report it - $r->print('Assigning: '.$3.' in '.$url.': '. - &Apache::lonnet::assignrole( - $ENV{'form.ccdomain'},$ENV{'form.ccuname'}, - $url,$3,$end,$start). - '
'); - # Handle students differently - if ($3 eq 'st') { - $url=~/^\/(\w+)\/(\w+)/; - my $cid=$1.'_'.$2; - $r->print('Add to classlist: '. - &Apache::lonnet::critical( - 'put:'.$ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}.':classlist:'. - &Apache::lonnet::escape( - $ENV{'form.ccuname'}.':'. - $ENV{'form.ccdomain'} ).'='. - &Apache::lonnet::escape($end.':'.$start), - $ENV{'course.'.$cid.'.home'}) - .'
'); - } - } elsif ($_=~/^form\.act\_([^\_]+)\_([^\_]+)$/) { + my $url='/'.$one.'/'.$two; + my $type = 'three'; + # split multiple sections + my %sections = (); + my $num_sections = &build_roles($env{'form.sec_'.$one.'_'.$two.'_'.$three},\%sections,$three); + my $credits; + if ($three eq 'st') { + if ($showcredits) { + my $defaultcredits = + &Apache::lonuserutils::get_defaultcredits($one,$two); + $credits = $env{'form.credits_'.$one.'_'.$two.'_'.$three}; + $credits =~ s/[^\d\.]//g; + if ($credits eq $defaultcredits) { + undef($credits); + } + } + } + if ($num_sections == 0) { + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$three,$start,$end,$one,$two,'',$context,$credits)); + } else { + my %curr_groups = + &Apache::longroup::coursegroups($one,$two); + my $emptysec = 0; + foreach my $sec (sort {$a cmp $b} keys(%sections)) { + $sec =~ s/\W//g; + if ($sec ne '') { + if (($sec eq 'none') || ($sec eq 'all') || + exists($curr_groups{$sec})) { + $disallowed{$sec} = $url; + next; + } + my $securl = $url.'/'.$sec; + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$securl,$three,$start,$end,$one,$two,$sec,$context,$credits)); + } else { + $emptysec = 1; + } + } + if ($emptysec) { + $r->print(&Apache::loncommon::commit_standardrole($udom,$uname,$url,$three,$start,$end,$one,$two,'',$context,$credits)); + } + } + 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 - my $start = ( $ENV{'form.start_'.$1.'_'.$2} ? - $ENV{'form.start_'.$1.'_'.$2} : + my $start = ( $env{'form.start_'.$1.'_'.$2} ? + $env{'form.start_'.$1.'_'.$2} : $now ); - my $end = ( $ENV{'form.end_'.$1.'_'.$2} ? - $ENV{'form.end_'.$1.'_'.$2} : + my $end = ( $env{'form.end_'.$1.'_'.$2} ? + $env{'form.end_'.$1.'_'.$2} : 0 ); - my $url='/'.$1.'/'; - # Assign the role and report it. - $r->print('Assigning: '.$2.' in '.$url.': '. - &Apache::lonnet::assignrole( - $ENV{'form.ccdomain'},$ENV{'form.ccuname'}, - $url,$2,$end,$start) - .'
'); - } - } - } # End of foreach (keys(%ENV)) - $r->print(''); + my $one = $1; + my $two = $2; + my $url='/'.$one.'/'; + # split multiple sections + my %sections = (); + 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,$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,$two,$start,$end,$one,undef,$sec,$context)); + } else { + $emptysec = 1; + } + } + if ($emptysec) { + $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.'


'); + } + 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.'')); + } 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('Please [_1]go back[_2] and choose a different section name.' + ,''); + if ($crstype eq 'Community') { + $r->print(&mt('If the member is currently logged-in to LON-CAPA, the new role can be displayed by using the "Check for changes" link on the Roles/Courses page.')); + } else { + $r->print(&mt('If the student is currently logged-in to LON-CAPA, the new role can be displayed by using the "Check for changes" link on the Roles/Courses page.')); + } + $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,$name) = @_; + my $quotachanged; + if (&Apache::lonnet::allowed('mpq',$env{'form.ccdomain'})) { + # Current user has quota modification privileges + if (ref($changeHash) eq 'HASH') { + $quotachanged = 1; + $changeHash->{$name.'quota'} = $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 ($context eq 'requestauthor') { + if (&Apache::lonnet::allowed('cau',$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; + if ($tool eq 'requestauthor') { + $changeHash->{$context} = $settool; + } else { + $changeHash->{$context.'.'.$tool} = $settool; + } + } + } + return $toolchanged; +} + +sub build_roles { + my ($sectionstr,$sections,$role) = @_; + my $num_sections = 0; + if ($sectionstr=~ /,/) { + my @secnums = split/,/,$sectionstr; + if ($role eq 'st') { + $secnums[0] =~ s/\W//g; + $$sections{$secnums[0]} = 1; + $num_sections = 1; + } else { + foreach my $sec (@secnums) { + $sec =~ ~s/\W//g; + if (!($sec eq "")) { + if (exists($$sections{$sec})) { + $$sections{$sec} ++; + } else { + $$sections{$sec} = 1; + $num_sections ++; + } + } + } + } + } else { + $sectionstr=~s/\W//g; + unless ($sectionstr eq '') { + $$sections{$sectionstr} = 1; + $num_sections ++; + } + } + + return $num_sections; +} + +# ========================================================== Custom Role Editor + +sub custom_role_editor { + my ($r,$context,$brcrum,$prefix,$permission) = @_; + my $action = $env{'form.customroleaction'}; + my ($rolename,$helpitem); + if ($action eq 'new') { + $rolename=$env{'form.newrolename'}; + } else { + $rolename=$env{'form.rolename'}; + } + + my ($crstype,$context); + if ($env{'request.course.id'}) { + $crstype = &Apache::loncommon::course_type(); + $context = 'course'; + $helpitem = 'Course_Editing_Custom_Roles'; + } else { + $context = 'domain'; + $crstype = 'course'; + $helpitem = 'Domain_Editing_Custom_Roles'; + } + + $rolename=~s/[^A-Za-z0-9]//gs; + if (!$rolename || $env{'form.phase'} eq 'pickrole') { + &print_username_entry_form($r,$context,undef,undef,undef,$crstype,$brcrum, + $permission); + return; + } + + my $formname = 'form1'; + my %privs=(); + my $body_top = '

'; +# ------------------------------------------------------- Does this role exist? + my ($rdummy,$roledef)= + &Apache::lonnet::get('roles',["rolesdef_$rolename"]); + if (($rdummy ne 'con_lost') && ($roledef ne '')) { + $body_top .= &mt('Existing Role').' "'; +# ------------------------------------------------- Get current role privileges + ($privs{'system'},$privs{'domain'},$privs{'course'})=split(/\_/,$roledef); + if ($privs{'system'} =~ /bre\&S/) { + if ($context eq 'domain') { + $crstype = 'Course'; + } elsif ($crstype eq 'Community') { + $privs{'system'} =~ s/bre\&S//; + } + } elsif ($context eq 'domain') { + $crstype = 'Course'; + } + } else { + $body_top .= &mt('New Role').' "'; + $roledef=''; + } + $body_top .= $rolename.'"

'; + +# ------------------------------------------------------- What can be assigned? + my %full=(); + my %levels=( + course => {}, + domain => {}, + system => {}, + ); + my %levelscurrent=( + course => {}, + domain => {}, + system => {}, + ); + &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent); + my ($jsback,$elements) = &crumb_utilities(); + my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype); + my $head_script = + &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname, + \%full,\@templateroles,$jsback); + push (@{$brcrum}, + {href => "javascript:backPage(document.$formname,'pickrole','')", + text => "Pick custom role", + faq => 282,bug=>'Instructor Interface',}, + {href => "javascript:backPage(document.$formname,'','')", + text => "Edit custom role", + faq => 282, + bug => 'Instructor Interface', + help => $helpitem} + ); + my $args = { bread_crumbs => $brcrum, + bread_crumbs_component => 'User Management'}; + $r->print(&Apache::loncommon::start_page('Custom Role Editor', + $head_script,$args). + $body_top); + $r->print('
'."\n". + &Apache::lonuserutils::custom_role_header($context,$crstype, + \@templateroles,$prefix)); + + $r->print(< + +ENDCCF + $r->print(&Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels, + \%levelscurrent,$prefix)); + $r->print(&Apache::loncommon::end_data_table(). + ''. + ''."\n".''."\n". + ''."\n". + ''); +} + +# ---------------------------------------------------------- Call to definerole +sub set_custom_role { + my ($r,$context,$brcrum,$prefix,$permission) = @_; + my $rolename=$env{'form.rolename'}; + $rolename=~s/[^A-Za-z0-9]//gs; + if (!$rolename) { + &custom_role_editor($r,$context,$brcrum,$prefix,$permission); + return; + } + my ($jsback,$elements) = &crumb_utilities(); + my $jscript = ''."\n"; + my $helpitem = 'Course_Editing_Custom_Roles'; + if ($context eq 'domain') { + $helpitem = 'Domain_Editing_Custom_Roles'; + } + 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 => $helpitem,} + ); + my $args = { bread_crumbs => $brcrum, + bread_crumbs_component => 'User Management'}; + $r->print(&Apache::loncommon::start_page('Save Custom Role',$jscript,$args)); + + my $newrole; + 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=''; + $newrole = 1; + } + $r->print($rolename.'"

'); +# ------------------------------------------------- Assign role and show result + + my $errmsg; + my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$prefix); + # Assign role and return result + my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'}, + $newprivs{'c'}); + if ($result ne 'ok') { + $errmsg = ': '.$result; + } + my $message = + &Apache::lonhtmlcommon::confirm_success( + &mt('Defining Role').$errmsg, ($result eq 'ok' ? 0 : 1)); + if ($env{'request.course.id'}) { + my $url='/'.$env{'request.course.id'}; + $url=~s/\_/\//g; + $result = + &Apache::lonnet::assigncustomrole( + $env{'user.domain'},$env{'user.name'}, + $url, + $env{'user.domain'},$env{'user.name'}, + $rolename,undef,undef,undef,$context); + if ($result ne 'ok') { + $errmsg = ': '.$result; + } + $message .= + '
' + .&Apache::lonhtmlcommon::confirm_success( + &mt('Assigning Role to Self').$errmsg, ($result eq 'ok' ? 0 : 1)); + } + $r->print( + &Apache::loncommon::confirmwrapper($message) + .'
' + .&Apache::lonhtmlcommon::actionbox([ + '
' + .&mt('Create or edit another custom role') + .'']) + .'
' + .&Apache::lonhtmlcommon::echo_form_input([]) + .'
' + ); } # ================================================================ Main Handler sub handler { my $r = shift; - if ($r->header_only) { - $r->content_type('text/html'); + &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK; } + my ($context,$crstype,$cid,$cnum,$cdom,$allhelpitems); - 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'})) || - (&Apache::lonnet::allowed('cca',$ENV{'request.role.domain'})) || - (&Apache::lonnet::allowed('mau',$ENV{'request.role.domain'}))) { - $r->content_type('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); - } - } else { - $ENV{'user.error.msg'}= - "/adm/createuser:mau:0:0:Cannot modify user data"; - return HTTP_NOT_ACCEPTABLE; - } - return OK; + if ($env{'request.course.id'}) { + $context = 'course'; + $crstype = &Apache::loncommon::course_type(); + } elsif ($env{'request.role'} =~ /^au\./) { + $context = 'author'; + } else { + $context = 'domain'; + } + + my ($permission,$allowed) = + &Apache::lonuserutils::get_permission($context,$crstype); + + if ($allowed) { + my @allhelp; + if ($context eq 'course') { + $cid = $env{'request.course.id'}; + $cdom = $env{'course.'.$cid.'.domain'}; + $cnum = $env{'course.'.$cid.'.num'}; + + if ($permission->{'cusr'}) { + push(@allhelp,'Course_Create_Class_List'); + } + if ($permission->{'view'} || $permission->{'cusr'}) { + push(@allhelp,('Course_Change_Privileges','Course_View_Class_List')); + } + if ($permission->{'custom'}) { + push(@allhelp,'Course_Editing_Custom_Roles'); + } + if ($permission->{'cusr'}) { + push(@allhelp,('Course_Add_Student','Course_Drop_Student')); + } + unless ($permission->{'cusr_section'}) { + if (&Apache::lonnet::auto_run($cnum,$cdom) && (($permission->{'cusr'}) || ($permission->{'view'}))) { + push(@allhelp,'Course_Automated_Enrollment'); + } + if ($permission->{'selfenrolladmin'}) { + push(@allhelp,'Course_Approve_Selfenroll'); + } + } + if ($permission->{'grp_manage'}) { + push(@allhelp,'Course_Manage_Group'); + } + if ($permission->{'view'} || $permission->{'cusr'}) { + push(@allhelp,'Course_User_Logs'); + } + } elsif ($context eq 'author') { + push(@allhelp,('Author_Change_Privileges','Author_Create_Coauthor_List', + 'Author_View_Coauthor_List','Author_User_Logs')); + } else { + if ($permission->{'cusr'}) { + push(@allhelp,'Domain_Change_Privileges'); + if ($permission->{'activity'}) { + push(@allhelp,'Domain_User_Access_Logs'); + } + push(@allhelp,('Domain_Create_Users','Domain_View_Users_List')); + if ($permission->{'custom'}) { + push(@allhelp,'Domain_Editing_Custom_Roles'); + } + push(@allhelp,('Domain_Role_Approvals','Domain_Username_Approvals','Domain_Change_Logs')); + } elsif ($permission->{'view'}) { + push(@allhelp,'Domain_View_Privileges'); + if ($permission->{'activity'}) { + push(@allhelp,'Domain_User_Access_Logs'); + } + push(@allhelp,('Domain_View_Users_List','Domain_Change_Logs')); + } + } + if (@allhelp) { + $allhelpitems = join(',',@allhelp); + } + } + + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['action','state','callingform','roletype','showrole','bulkaction','popup','phase', + 'username','domain','srchterm','srchdomain','srchin','srchby','srchtype','queue']); + &Apache::lonhtmlcommon::clear_breadcrumbs(); + my $args; + my $brcrum = []; + my $bread_crumbs_component = 'User Management'; + if (($env{'form.action'} ne 'dateselect') && ($env{'form.action'} ne 'displayuserreq')) { + $brcrum = [{href=>"/adm/createuser", + text=>"User Management", + help=>$allhelpitems} + ]; + } + if (!$allowed) { + if ($context eq 'course') { + $r->internal_redirect('/adm/viewclasslist'); + return OK; + } + $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; + + my $showcredits; + if ((($context eq 'course') && ($crstype eq 'Course')) || + ($context eq 'domain')) { + my %domdefaults = + &Apache::lonnet::get_domain_defaults($env{'request.role.domain'}); + if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'}) { + $showcredits = 1; + } + } + + # 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'}) { + my $helpitem = 'Course_Create_Class_List'; + if ($context eq 'author') { + $helpitem = 'Author_Create_Coauthor_List'; + } elsif ($context eq 'domain') { + $helpitem = 'Domain_Create_Users'; + } + push(@{$brcrum}, + { href => '/adm/createuser?action=upload&state=', + text => 'Upload Users List', + help => $helpitem, + }); + $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') { + my $result = + &Apache::lonuserutils::print_upload_manager_form($r,$context, + $permission, + $crstype,$showcredits); + if ($result eq 'missingdata') { + delete($env{'form.state'}); + &Apache::lonuserutils::print_first_users_upload_form($r,$context); + } + } elsif ($env{'form.state'} eq 'enrolling') { + if ($env{'form.datatoken'}) { + my $result = &Apache::lonuserutils::upfile_drop_add($r,$context, + $permission, + $showcredits); + if ($result eq 'missingdata') { + delete($env{'form.state'}); + &Apache::lonuserutils::print_first_users_upload_form($r,$context); + } elsif ($result eq 'invalidhome') { + $env{'form.state'} = 'got_file'; + delete($env{'form.lcserver'}); + my $result = + &Apache::lonuserutils::print_upload_manager_form($r,$context,$permission, + $crstype,$showcredits); + if ($result eq 'missingdata') { + delete($env{'form.state'}); + &Apache::lonuserutils::print_first_users_upload_form($r,$context); + } + } + } else { + delete($env{'form.state'}); + &Apache::lonuserutils::print_first_users_upload_form($r,$context); + } + } else { + &Apache::lonuserutils::print_first_users_upload_form($r,$context); + } + $r->print('
'); + } elsif (((($env{'form.action'} eq 'singleuser') || ($env{'form.action'} + eq 'singlestudent')) && ($permission->{'cusr'})) || + (($env{'form.action'} eq 'singleuser') && ($permission->{'view'})) || + (($env{'form.action'} eq 'accesslogs') && ($permission->{'activity'}))) { + 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') || ($phase eq 'activity')) { + 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,$permission); + } 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, + $showcredits); + } + } 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') || ($env{'form.action'} eq 'accesslogs')) { + my ($ccuname,$ccdomain,$uhome); + 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.action'} eq 'accesslogs') { + my $uhome; + if (($ccuname ne '') && ($ccdomain ne '')) { + $uhome = &Apache::lonnet::homeserver($ccuname,$ccdomain); + } + if (($uhome eq '') || ($uhome eq 'no_host')) { + $env{'form.phase'} = ''; + undef($forcenewuser); + #if ($response) { + # unless ($response =~ m{\Q

\E$}) { + # $response .= '

'; + # } + #} + &print_username_entry_form($r,$context,$response,$srch, + $forcenewuser,$crstype,$brcrum, + $permission); + } else { + &print_useraccesslogs_display($r,$ccuname,$ccdomain,$permission,$brcrum); + } + } else { + if ($env{'form.forcenewuser'}) { + $response = ''; + } + &print_user_modification_page($r,$ccuname,$ccdomain, + $srch,$response,$context, + $permission,$crstype,$brcrum); + } + } 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, + $permission); + } + } elsif ($env{'form.phase'} eq 'userpicked') { + my $ccuname = &LONCAPA::clean_username($env{'form.seluname'}); + my $ccdomain = &LONCAPA::clean_domain($env{'form.seludom'}); + if ($env{'form.action'} eq 'accesslogs') { + &print_useraccesslogs_display($r,$ccuname,$ccdomain,$permission,$brcrum); + } else { + &print_user_modification_page($r,$ccuname,$ccdomain,$srch,'', + $context,$permission,$crstype, + $brcrum); + } + } elsif ($env{'form.action'} eq 'accesslogs') { + my $ccuname = &LONCAPA::clean_username($env{'form.accessuname'}); + my $ccdomain = &LONCAPA::clean_domain($env{'form.accessudom'}); + &print_useraccesslogs_display($r,$ccuname,$ccdomain,$permission,$brcrum); + } + } elsif ($env{'form.phase'} eq 'update_user_data') { + &update_user_data($r,$context,$crstype,$brcrum,$showcredits,$permission); + } else { + &print_username_entry_form($r,$context,undef,$srch,undef,$crstype, + $brcrum,$permission); + } + } elsif ($env{'form.action'} eq 'custom' && $permission->{'custom'}) { + my $prefix; + if ($env{'form.phase'} eq 'set_custom_roles') { + &set_custom_role($r,$context,$brcrum,$prefix,$permission); + } else { + &custom_role_editor($r,$context,$brcrum,$prefix,$permission); + } + } elsif (($env{'form.action'} eq 'processauthorreq') && + ($permission->{'cusr'}) && + (&Apache::lonnet::allowed('cau',$env{'request.role.domain'}))) { + push(@{$brcrum}, + {href => '/adm/createuser?action=processauthorreq', + text => 'Authoring Space requests', + help => 'Domain_Role_Approvals'}); + $bread_crumbs_component = 'Authoring requests'; + if ($env{'form.state'} eq 'done') { + push(@{$brcrum}, + {href => '/adm/createuser?action=authorreqqueue', + text => 'Result', + help => 'Domain_Role_Approvals'}); + $bread_crumbs_component = 'Authoring request result'; + } + $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + my $js = &usernamerequest_javascript(); + $r->print(&header(&add_script($js),$args)); + if (!exists($env{'form.state'})) { + $r->print(&Apache::loncoursequeueadmin::display_queued_requests('requestauthor', + $env{'request.role.domain'})); + } elsif ($env{'form.state'} eq 'done') { + $r->print('

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

'."\n"); + $r->print(&Apache::loncoursequeueadmin::update_request_queue('requestauthor', + $env{'request.role.domain'})); + } + } elsif (($env{'form.action'} eq 'processusernamereq') && + ($permission->{'cusr'}) && + (&Apache::lonnet::allowed('cau',$env{'request.role.domain'}))) { + push(@{$brcrum}, + {href => '/adm/createuser?action=processusernamereq', + text => 'LON-CAPA account requests', + help => 'Domain_Username_Approvals'}); + $bread_crumbs_component = 'Account requests'; + if ($env{'form.state'} eq 'done') { + push(@{$brcrum}, + {href => '/adm/createuser?action=usernamereqqueue', + text => 'Result', + help => 'Domain_Username_Approvals'}); + $bread_crumbs_component = 'LON-CAPA account request result'; + } + $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + my $js = &usernamerequest_javascript(); + $r->print(&header(&add_script($js),$args)); + if (!exists($env{'form.state'})) { + $r->print(&Apache::loncoursequeueadmin::display_queued_requests('requestusername', + $env{'request.role.domain'})); + } elsif ($env{'form.state'} eq 'done') { + $r->print('

'.&mt('LON-CAPA account request processing').'

'."\n"); + $r->print(&Apache::loncoursequeueadmin::update_request_queue('requestusername', + $env{'request.role.domain'})); + } + } elsif (($env{'form.action'} eq 'displayuserreq') && + ($permission->{'cusr'})) { + my $dom = $env{'form.domain'}; + my $uname = $env{'form.username'}; + my $warning; + if (($dom =~ /^$match_domain$/) && (&Apache::lonnet::domain($dom) ne '')) { + if (($dom eq $env{'request.role.domain'}) && (&Apache::lonnet::allowed('ccc',$dom))) { + if (($uname =~ /^$match_username$/) && ($env{'form.queue'} eq 'approval')) { + my $uhome = &Apache::lonnet::homeserver($uname,$dom); + if ($uhome eq 'no_host') { + my $queue = $env{'form.queue'}; + my $reqkey = &escape($uname).'_'.$queue; + my $namespace = 'usernamequeue'; + my $domconfig = &Apache::lonnet::get_domainconfiguser($dom); + my %queued = + &Apache::lonnet::get($namespace,[$reqkey],$dom,$domconfig); + unless ($queued{$reqkey}) { + $warning = &mt('No information was found for this LON-CAPA account request.'); + } + } else { + $warning = &mt('A LON-CAPA account already exists for the requested username and domain.'); + } + } else { + $warning = &mt('LON-CAPA account request status check is for an invalid username.'); + } + } else { + $warning = &mt('You do not have rights to view LON-CAPA account requests in the domain specified.'); + } + } else { + $warning = &mt('LON-CAPA account request status check is for an invalid domain.'); + } + my $args = { only_body => 1 }; + $r->print(&header(undef,$args). + '

'.&mt('LON-CAPA Account Request Details').'

'); + if ($warning ne '') { + $r->print('
'.$warning.'
'); + } else { + my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info(); + my $domconfiguser = &Apache::lonnet::get_domainconfiguser($dom); + my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom); + if (ref($domconfig{'usercreation'}) eq 'HASH') { + if (ref($domconfig{'usercreation'}{'cancreate'}) eq 'HASH') { + if (ref($domconfig{'usercreation'}{'cancreate'}{'emailusername'}) eq 'HASH') { + my %info = + &Apache::lonnet::get('nohist_requestedusernames',[$uname],$dom,$domconfiguser); + if (ref($info{$uname}) eq 'HASH') { + my $usertype = $info{$uname}{'inststatus'}; + unless ($usertype) { + $usertype = 'default'; + } + my ($showstatus,$showemail,$pickstart); + my $numextras = 0; + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + if ((ref($types) eq 'ARRAY') && (@{$types} > 0)) { + if (ref($usertypes) eq 'HASH') { + if ($usertypes->{$usertype}) { + $showstatus = $usertypes->{$usertype}; + } else { + $showstatus = $othertitle; + } + if ($showstatus) { + $numextras ++; + } + } + } + if (($info{$uname}{'email'} ne '') && ($info{$uname}{'email'} ne $uname)) { + $showemail = $info{$uname}{'email'}; + $numextras ++; + } + if (ref($domconfig{'usercreation'}{'cancreate'}{'emailusername'}{$usertype}) eq 'HASH') { + if ((ref($infofields) eq 'ARRAY') && (ref($infotitles) eq 'HASH')) { + $pickstart = 1; + $r->print('
'.&Apache::lonhtmlcommon::start_pick_box()); + my ($num,$count); + $count = scalar(keys(%{$domconfig{'usercreation'}{'cancreate'}{'emailusername'}{$usertype}})); + $count += $numextras; + foreach my $field (@{$infofields}) { + next unless ($domconfig{'usercreation'}{'cancreate'}{'emailusername'}{$usertype}{$field}); + next unless ($infotitles->{$field}); + $r->print(&Apache::lonhtmlcommon::row_title($infotitles->{$field}). + $info{$uname}{$field}); + $num ++; + unless ($count == $num) { + $r->print(&Apache::lonhtmlcommon::row_closure()); + } + } + } + } + if ($numextras) { + unless ($pickstart) { + $r->print('
'.&Apache::lonhtmlcommon::start_pick_box()); + $pickstart = 1; + } + if ($showemail) { + my $closure = ''; + unless ($showstatus) { + $closure = 1; + } + $r->print(&Apache::lonhtmlcommon::row_title(&mt('E-mail address')). + $showemail. + &Apache::lonhtmlcommon::row_closure($closure)); + } + if ($showstatus) { + $r->print(&Apache::lonhtmlcommon::row_title(&mt('Status type[_1](self-reported)','
')). + $showstatus. + &Apache::lonhtmlcommon::row_closure(1)); + } + } + if ($pickstart) { + $r->print(&Apache::lonhtmlcommon::end_pick_box().'
'); + } else { + $r->print('
'.&mt('No information to display for this account request.').'
'); + } + } else { + $r->print('
'.&mt('No information available for this account request.').'
'); + } + } + } + } + } + $r->print(&close_popup_form()); + } elsif (($env{'form.action'} eq 'listusers') && + ($permission->{'view'} || $permission->{'cusr'})) { + my $helpitem = 'Course_View_Class_List'; + if ($context eq 'author') { + $helpitem = 'Author_View_Coauthor_List'; + } elsif ($context eq 'domain') { + $helpitem = 'Domain_View_Users_List'; + } + if ($env{'form.phase'} eq 'bulkchange') { + push(@{$brcrum}, + {href => '/adm/createuser?action=listusers', + text => "List Users"}, + {href => "/adm/createuser", + text => "Result", + help => $helpitem}); + $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 => $helpitem}); + $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'; + my $hidecall = "hide_searching();"; + 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($context)."\n". + &Apache::loncommon::check_uncheck_jscript(); + my $js = &add_script($jscript).$cb_jscript; + my $loadcode = + &Apache::lonuserutils::course_selector_loadcode($formname); + if ($loadcode ne '') { + $args->{add_entries} = {onload => "$loadcode;$hidecall"}; + } else { + $args->{add_entries} = {onload => $hidecall}; + } + $r->print(&header($js,$args)); + } else { + $args->{add_entries} = {onload => $hidecall}; + $jscript = &verify_user_display($context). + &Apache::loncommon::check_uncheck_jscript(); + $r->print(&header(&add_script($jscript),$args)); + } + &Apache::lonuserutils::print_userlist($r,undef,$permission,$context, + $formname,$totcodes,$codetitles,$idlist,$idlist_titles, + $showcredits); + } + } 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,$showcredits)); + } 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') { + if ($permission->{selfenrolladmin}) { + my %currsettings = ( + selfenroll_types => $env{'course.'.$cid.'.internal.selfenroll_types'}, + selfenroll_registered => $env{'course.'.$cid.'.internal.selfenroll_registered'}, + selfenroll_section => $env{'course.'.$cid.'.internal.selfenroll_section'}, + selfenroll_notifylist => $env{'course.'.$cid.'.internal.selfenroll_notifylist'}, + selfenroll_approval => $env{'course.'.$cid.'.internal.selfenroll_approval'}, + selfenroll_limit => $env{'course.'.$cid.'.internal.selfenroll_limit'}, + selfenroll_cap => $env{'course.'.$cid.'.internal.selfenroll_cap'}, + selfenroll_start_date => $env{'course.'.$cid.'.internal.selfenroll_start_date'}, + selfenroll_end_date => $env{'course.'.$cid.'.internal.selfenroll_end_date'}, + selfenroll_start_access => $env{'course.'.$cid.'.internal.selfenroll_start_access'}, + selfenroll_end_access => $env{'course.'.$cid.'.internal.selfenroll_end_access'}, + default_enrollment_start_date => $env{'course.'.$cid.'.default_enrollment_start_date'}, + default_enrollment_end_date => $env{'course.'.$cid.'.default_enrollment_end_date'}, + uniquecode => $env{'course.'.$cid.'.internal.uniquecode'}, + ); + 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,'course',$cid,$cdom,$cnum,\%currsettings); + } 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,$cid,$cdom,$cnum,$context,$crstype,\%currsettings); + } + } else { + $r->print(&header(undef,{'no_nav_bar' => 1}). + ''.&mt('You do not have permission to configure self-enrollment').''); + } + } elsif ($env{'form.action'} eq 'selfenrollqueue') { + if ($permission->{selfenrolladmin}) { + push(@{$brcrum}, + {href => '/adm/createuser?action=selfenrollqueue', + text => 'Enrollment requests', + help => 'Course_Approve_Selfenroll'}); + $bread_crumbs_component = 'Enrollment requests'; + if ($env{'form.state'} eq 'done') { + push(@{$brcrum}, + {href => '/adm/createuser?action=selfenrollqueue', + text => 'Result', + help => 'Course_Approve_Selfenroll'}); + $bread_crumbs_component = 'Enrollment result'; + } + $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + $r->print(&header(undef,$args)); + 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)); + } + } else { + $r->print(&header(undef,{'no_nav_bar' => 1}). + ''.&mt('You do not have permission to manage self-enrollment').''); + } + } elsif ($env{'form.action'} eq 'changelogs') { + if ($permission->{cusr} || $permission->{view}) { + &print_userchangelogs_display($r,$context,$permission,$brcrum); + } else { + $r->print(&header(undef,{'no_nav_bar' => 1}). + ''.&mt('You do not have permission to view change logs').''); + } + } elsif ($env{'form.action'} eq 'helpdesk') { + if (($permission->{'owner'}) || ($permission->{'co-owner'})) { + if ($env{'form.state'} eq 'process') { + if ($permission->{'owner'}) { + &update_helpdeskaccess($r,$permission,$brcrum); + } else { + &print_helpdeskaccess_display($r,$permission,$brcrum); + } + } else { + &print_helpdeskaccess_display($r,$permission,$brcrum); + } + } else { + $r->print(&header(undef,{'no_nav_bar' => 1}). + ''.&mt('You do not have permission to view helpdesk access').''); + } + } 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; +} + +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 usernamerequest_javascript { + my $js = <
+ +

+END +} + +sub verify_user_display { + my ($context) = @_; + my %lt = &Apache::lonlocal::texthash ( + course => 'course(s): description, section(s), status', + community => 'community(s): description, section(s), status', + author => 'author', + ); + my $photos; + if (($context eq 'course') && $env{'request.course.id'}) { + $photos = $env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}; + } + my $output = <<"END"; + +function hide_searching() { + if (document.getElementById('searching')) { + document.getElementById('searching').style.display = 'none'; + } + return; +} + +function display_update() { + document.studentform.action.value = 'listusers'; + document.studentform.phase.value = 'display'; + document.studentform.submit(); +} + +function updateCols(caller) { + var context = '$context'; + var photos = '$photos'; + if (caller == 'Status') { + if ((context == 'domain') && + ((document.studentform.roletype.options[document.studentform.roletype.selectedIndex].value == 'course') || + (document.studentform.roletype.options[document.studentform.roletype.selectedIndex].value == 'community'))) { + document.getElementById('showcolstatus').checked = false; + document.getElementById('showcolstatus').disabled = 'disabled'; + document.getElementById('showcolstart').checked = false; + document.getElementById('showcolend').checked = false; + } else { + if (document.studentform.Status.options[document.studentform.Status.selectedIndex].value == 'Any') { + document.getElementById('showcolstatus').checked = true; + document.getElementById('showcolstatus').disabled = ''; + document.getElementById('showcolstart').checked = true; + document.getElementById('showcolend').checked = true; + } else { + document.getElementById('showcolstatus').checked = false; + document.getElementById('showcolstatus').disabled = 'disabled'; + document.getElementById('showcolstart').checked = false; + document.getElementById('showcolend').checked = false; + } + } + } + if (caller == 'output') { + if (photos == 1) { + if (document.getElementById('showcolphoto')) { + var photoitem = document.getElementById('showcolphoto'); + if (document.studentform.output.options[document.studentform.output.selectedIndex].value == 'html') { + photoitem.checked = true; + photoitem.disabled = ''; + } else { + photoitem.checked = false; + photoitem.disabled = 'disabled'; + } + } + } + } + if (caller == 'showrole') { + if ((document.studentform.showrole.options[document.studentform.showrole.selectedIndex].value == 'Any') || + (document.studentform.showrole.options[document.studentform.showrole.selectedIndex].value == 'cr')) { + document.getElementById('showcolrole').checked = true; + document.getElementById('showcolrole').disabled = ''; + } else { + document.getElementById('showcolrole').checked = false; + document.getElementById('showcolrole').disabled = 'disabled'; + } + if (context == 'domain') { + var quotausageshow = 0; + if ((document.studentform.roletype.options[document.studentform.roletype.selectedIndex].value == 'course') || + (document.studentform.roletype.options[document.studentform.roletype.selectedIndex].value == 'community')) { + document.getElementById('showcolstatus').checked = false; + document.getElementById('showcolstatus').disabled = 'disabled'; + document.getElementById('showcolstart').checked = false; + document.getElementById('showcolend').checked = false; + } else { + if (document.studentform.Status.options[document.studentform.Status.selectedIndex].value == 'Any') { + document.getElementById('showcolstatus').checked = true; + document.getElementById('showcolstatus').disabled = ''; + document.getElementById('showcolstart').checked = true; + document.getElementById('showcolend').checked = true; + } + } + if (document.studentform.roletype.options[document.studentform.roletype.selectedIndex].value == 'domain') { + document.getElementById('showcolextent').disabled = 'disabled'; + document.getElementById('showcolextent').checked = 'false'; + document.getElementById('showextent').style.display='none'; + document.getElementById('showcoltextextent').innerHTML = ''; + if ((document.studentform.showrole.options[document.studentform.showrole.selectedIndex].value == 'au') || + (document.studentform.showrole.options[document.studentform.showrole.selectedIndex].value == 'Any')) { + if (document.getElementById('showcolauthorusage')) { + document.getElementById('showcolauthorusage').disabled = ''; + } + if (document.getElementById('showcolauthorquota')) { + document.getElementById('showcolauthorquota').disabled = ''; + } + quotausageshow = 1; + } + } else { + document.getElementById('showextent').style.display='block'; + document.getElementById('showextent').style.textAlign='left'; + document.getElementById('showextent').style.textFace='normal'; + if (document.studentform.roletype.options[document.studentform.roletype.selectedIndex].value == 'author') { + document.getElementById('showcolextent').disabled = ''; + document.getElementById('showcolextent').checked = 'true'; + document.getElementById('showcoltextextent').innerHTML="$lt{'author'}"; + } else { + document.getElementById('showcolextent').disabled = ''; + document.getElementById('showcolextent').checked = 'true'; + if (document.studentform.roletype.options[document.studentform.roletype.selectedIndex].value == 'community') { + document.getElementById('showcoltextextent').innerHTML="$lt{'community'}"; + } else { + document.getElementById('showcoltextextent').innerHTML="$lt{'course'}"; + } + } + } + if (quotausageshow == 0) { + if (document.getElementById('showcolauthorusage')) { + document.getElementById('showcolauthorusage').checked = false; + document.getElementById('showcolauthorusage').disabled = 'disabled'; + } + if (document.getElementById('showcolauthorquota')) { + document.getElementById('showcolauthorquota').checked = false; + document.getElementById('showcolauthorquota').disabled = 'disabled'; + } + } + } + } + return; +} + +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 => 'List and Modify Multiple Course Users', + }, + community => { + upload => 'Upload a File of Community Users', + singleuser => 'Add/Modify a Community User', + listusers => 'List and Modify Multiple 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.', + }, + ); + if ($linkcontext eq 'domain') { + unless ($permission->{'cusr'}) { + $links{'domain'}{'singleuser'} = 'View a User'; + $linktitles{'domain'}{'singleuser'} = 'View information about a user in the domain'; + } + } elsif ($linkcontext eq 'course') { + unless ($permission->{'cusr'}) { + $links{'course'}{'singleuser'} = 'View a Course User'; + $linktitles{'course'}{'singleuser'} = 'View information about a user in this course'; + $links{'course'}{'listusers'} = 'List Course Users'; + $linktitles{'course'}{'listusers'} = 'Show information about users in this course'; + } + } elsif ($linkcontext eq 'community') { + unless ($permission->{'cusr'}) { + $links{'community'}{'singleuser'} = 'View a Community User'; + $linktitles{'community'}{'singleuser'} = 'View information about a user in this community'; + $links{'community'}{'listusers'} = 'List Community Users'; + $linktitles{'community'}{'listusers'} = 'Show information about 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->{'view'} || $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[0]->{items} }, # Single Users + { + linktext => 'User Access Log', + icon => 'document-properties.png', + #help => 'Domain_User_Access_Logs', + url => '/adm/createuser?action=accesslogs', + permission => $permission->{'activity'}, + linktitle => 'View user access log.', + } + ); + + 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 => 'Authoring Space Requests', + icon => 'selfenrl-queue.png', + #help => 'Domain_Role_Approvals', + url => '/adm/createuser?action=processauthorreq', + permission => $permission->{'cusr'}, + linktitle => 'Approve or reject author role requests', + }, + { + linktext => 'LON-CAPA Account Requests', + icon => 'list-add.png', + #help => 'Domain_Username_Approvals', + url => '/adm/createuser?action=processusernamereq', + permission => $permission->{'cusr'}, + linktitle => 'Approve or reject LON-CAPA account requests', + }, + { + linktext => 'Change Log', + icon => 'document-properties.png', + #help => 'Course_User_Logs', + url => '/adm/createuser?action=changelogs', + permission => ($permission->{'cusr'} || $permission->{'view'}), + linktitle => 'View change log.', + }, + ); + + }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 => 'Helpdesk Access', + icon => 'helpdesk-access.png', + #help => 'Course_Helpdesk_Access', + url => '/adm/createuser?action=helpdesk', + permission => ($permission->{'owner'} || $permission->{'co-owner'}), + linktitle => 'Helpdesk access options', + }, + { + 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->{'view'} || $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->{'selfenrolladmin'}, + 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'}) || + ($permission->{'view'}))), + 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->{'selfenrolladmin'}, + linktitle => 'Configure user self-enrollment.', + }, + ); + } + } elsif ($context eq 'author') { + push(@{ $menu[2]->{items} }, #Category: Administration + { + linktext => 'Change Log', + icon => 'document-properties.png', + #help => 'Course_User_Logs', + url => '/adm/createuser?action=changelogs', + permission => $permission->{'cusr'}, + linktitle => 'View change log.', + }, + ); + } + 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,$cid,$cdom,$cnum,$currsettings,$additional,$readonly) = @_; + my $crstype = &Apache::loncommon::course_type(); + my $formname = 'selfenroll'; + my $nolink = 1; + my ($row,$lt) = &Apache::lonuserutils::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 $disabled; + if ($readonly) { + $disabled = ' disabled="disabled"'; + } + &js_escape(\%alerts); + 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 $visactions = &cat_visibility(); + my ($cathash,%cattype); + my %domconfig = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom); + if (ref($domconfig{'coursecategories'}) eq 'HASH') { + $cathash = $domconfig{'coursecategories'}{'cats'}; + $cattype{'auth'} = $domconfig{'coursecategories'}{'auth'}; + $cattype{'unauth'} = $domconfig{'coursecategories'}{'unauth'}; + if ($cattype{'auth'} eq '') { + $cattype{'auth'} = 'std'; + } + if ($cattype{'unauth'} eq '') { + $cattype{'unauth'} = 'std'; + } + } else { + $cathash = {}; + $cattype{'auth'} = 'std'; + $cattype{'unauth'} = 'std'; + } + if (($cattype{'auth'} eq 'none') && ($cattype{'unauth'} eq 'none')) { + $r->print('
'.$visactions->{'miss'}.'
'.$visactions->{'yous'}. + '
'. + '
'.$visactions->{'take'}.'
    '. + '
  • '.$visactions->{'dc_chgconf'}.'
  • '. + '
'); + } elsif (($cattype{'auth'} !~ /^(std|domonly)$/) && ($cattype{'unauth'} !~ /^(std|domonly)$/)) { + if ($currsettings->{'uniquecode'}) { + $r->print(''.$visactions->{'vis'}.''); + } else { + $r->print('
'.$visactions->{'miss'}.'
'.$visactions->{'yous'}. + '
'. + '
'.$visactions->{'take'}.'
    '. + '
  • '.$visactions->{'dc_setcode'}.'
  • '. + '

'); + } + } else { + my ($visible,$cansetvis,$vismsgs) = &visible_in_stdcat($cdom,$cnum,\%domconfig); + 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 .= '

'; + } + } + } + my $actionhref = '/adm/createuser'; + if ($context eq 'domain') { + $actionhref = '/adm/modifycourse'; + } + + my %noedit; + unless ($context eq 'domain') { + %noedit = &get_noedit_fields($cdom,$cnum,$crstype,$row); + } + $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; + if (ref($currsettings) eq 'HASH') { + $curr_types = $currsettings->{'selfenroll_types'}; + } + if ($noedit{$item}) { + if ($curr_types eq '*') { + $output .= &mt('Any user in any domain'); + } else { + my @entries = split(/;/,$curr_types); + if (@entries > 0) { + $output .= '
    '; + foreach my $entry (@entries) { + my ($currdom,$typestr) = split(/:/,$entry); + next if ($typestr eq ''); + my $domdesc = &Apache::lonnet::domain($currdom); + my @currinsttypes = split(',',$typestr); + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($currdom); + if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) { + $usertypes->{'any'} = &mt('any user'); + if (keys(%{$usertypes}) > 0) { + $usertypes->{'other'} = &mt('other users'); + } + my @longinsttypes = map { $usertypes->{$_}; } @currinsttypes; + $output .= '
  • '.$domdesc.':'.join(', ',@longinsttypes).'
  • '; + } + } + $output .= '
'; + } else { + $output .= &mt('None'); + } + } + $output .= '
'.&mt('(Set by Domain Coordinator)'); + next; + } + 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,$readonly).'' + .&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,'','','',$readonly) + .'' + .''.&Apache::loncommon::end_data_table_row() + .&Apache::loncommon::end_data_table(); + } elsif ($item eq 'registered') { + my ($regon,$regoff); + my $registered; + if (ref($currsettings) eq 'HASH') { + $registered = $currsettings->{'selfenroll_registered'}; + } + if ($noedit{$item}) { + if ($registered) { + $output .= &mt('Must be registered in course'); + } else { + $output .= &mt('No requirement'); + } + $output .= '
'.&mt('(Set by Domain Coordinator)'); + next; + } + if ($registered) { + $regon = ' checked="checked" '; + $regoff = ''; + } else { + $regon = ''; + $regoff = ' checked="checked" '; + } + $output .= '  '; + } elsif ($item eq 'enroll_dates') { + my ($starttime,$endtime); + if (ref($currsettings) eq 'HASH') { + $starttime = $currsettings->{'selfenroll_start_date'}; + $endtime = $currsettings->{'selfenroll_end_date'}; + if ($starttime eq '') { + $starttime = $currsettings->{'default_enrollment_start_date'}; + } + if ($endtime eq '') { + $endtime = $currsettings->{'default_enrollment_end_date'}; + } + } + if ($noedit{$item}) { + $output .= &mt('From: [_1], to: [_2]',&Apache::lonlocal::locallocaltime($starttime), + &Apache::lonlocal::locallocaltime($endtime)); + $output .= '
'.&mt('(Set by Domain Coordinator)'); + next; + } + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_start_date',$starttime, + $disabled,undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_end_date',$endtime, + $disabled,undef,undef,undef,undef,undef,undef,$nolink); + $output .= &selfenroll_date_forms($startform,$endform); + } elsif ($item eq 'access_dates') { + my ($starttime,$endtime); + if (ref($currsettings) eq 'HASH') { + $starttime = $currsettings->{'selfenroll_start_access'}; + $endtime = $currsettings->{'selfenroll_end_access'}; + if ($starttime eq '') { + $starttime = $currsettings->{'default_enrollment_start_date'}; + } + if ($endtime eq '') { + $endtime = $currsettings->{'default_enrollment_end_date'}; + } + } + if ($noedit{$item}) { + $output .= &mt('From: [_1], to: [_2]',&Apache::lonlocal::locallocaltime($starttime), + &Apache::lonlocal::locallocaltime($endtime)); + $output .= '
'.&mt('(Set by Domain Coordinator)'); + next; + } + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_start_access',$starttime, + $disabled,undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'selfenroll_end_access',$endtime, + $disabled,undef,undef,undef,undef,undef,undef,$nolink); + $output .= &selfenroll_date_forms($startform,$endform); + } elsif ($item eq 'section') { + my $currsec; + if (ref($currsettings) eq 'HASH') { + $currsec = $currsettings->{'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; + } + } + if ($noedit{$item}) { + if ($currsec ne '') { + $output .= $currsec; + } else { + $output .= &mt('No specific section'); + } + $output .= '
'.&mt('(Set by Domain Coordinator)'); + next; + } + my $sections_select = + &Apache::lonuserutils::course_sections(\%sections_count,'st',$currsec,$disabled); + $output .= ''."\n". + ''."\n". + '
'.&mt('Existing sections')."\n". + '
'.$sections_select.'
'. + &mt('New section').'
'."\n". + ''."\n". + ''."\n". + '
'."\n"; + } elsif ($item eq 'approval') { + my ($currnotified,$currapproval,%appchecked); + my %selfdescs = &Apache::lonuserutils::selfenroll_default_descs(); + if (ref($currsettings) eq 'HASH') { + $currnotified = $currsettings->{'selfenroll_notifylist'}; + $currapproval = $currsettings->{'selfenroll_approval'}; + } + if ($currapproval !~ /^[012]$/) { + $currapproval = 0; + } + if ($noedit{$item}) { + $output .= $selfdescs{'approval'}{$currapproval}. + '
'.&mt('(Set by Domain Coordinator)'); + next; + } + $appchecked{$currapproval} = ' checked="checked"'; + for my $i (0..2) { + $output .= ''.(' 'x2); + } + 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) { + my $style; + unless ($currapproval) { + $style = ' style="display: none;"'; + } + $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,$currlim,$currcap); + if (ref($currsettings) eq 'HASH') { + $currlim = $currsettings->{'selfenroll_limit'}; + $currcap = $currsettings->{'selfenroll_cap'}; + } + if ($noedit{$item}) { + if (($currlim eq 'allstudents') || ($currlim eq 'selfenrolled')) { + if ($currlim eq 'allstudents') { + $output .= &mt('Limit by total students'); + } elsif ($currlim eq 'selfenrolled') { + $output .= &mt('Limit by total self-enrolled students'); + } + $output .= ' '.&mt('Maximum: [_1]',$currcap). + '
'.&mt('(Set by Domain Coordinator)'); + } else { + $output .= &mt('No limit').'
'.&mt('(Set by Domain Coordinator)'); + } + next; + } + if ($currlim eq 'allstudents') { + $crslimit = ' checked="checked" '; + $selflimit = ' '; + $nolimit = ' '; + } elsif ($currlim eq 'selfenrolled') { + $crslimit = ' '; + $selflimit = ' checked="checked" '; + $nolimit = ' '; + } else { + $crslimit = ' '; + $selflimit = ' '; + $nolimit = ' checked="checked" '; + } + $output .= ''. + '
 '. + (' 'x3).&mt('Maximum number allowed: '). + '
'; + } + $output .= &Apache::lonhtmlcommon::row_closure(1); + } + } + $output .= &Apache::lonhtmlcommon::end_pick_box().'
'; + unless ($readonly) { + $output .= ''; + } + $output .= '' + .''."\n" + .$additional.''; + $r->print($output); + return; +} + +sub get_noedit_fields { + my ($cdom,$cnum,$crstype,$row) = @_; + my %noedit; + if (ref($row) eq 'ARRAY') { + my %settings = &Apache::lonnet::get('environment',['internal.coursecode','internal.textbook', + 'internal.selfenrollmgrdc', + 'internal.selfenrollmgrcc'],$cdom,$cnum); + my $type = &Apache::lonuserutils::get_extended_type($cdom,$cnum,$crstype,\%settings); + my (%specific_managebydc,%specific_managebycc,%default_managebydc); + map { $specific_managebydc{$_} = 1; } (split(/,/,$settings{'internal.selfenrollmgrdc'})); + map { $specific_managebycc{$_} = 1; } (split(/,/,$settings{'internal.selfenrollmgrcc'})); + my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom); + map { $default_managebydc{$_} = 1; } (split(/,/,$domdefaults{$type.'selfenrolladmdc'})); + + foreach my $item (@{$row}) { + next if ($specific_managebycc{$item}); + if (($specific_managebydc{$item}) || ($default_managebydc{$item})) { + $noedit{$item} = 1; + } + } + } + return %noedit; } +sub visible_in_stdcat { + my ($cdom,$cnum,$domconf) = @_; + my ($cathash,%settable,@vismsgs,$cansetvis,$visible); + unless (ref($domconf) eq 'HASH') { + return ($visible,$cansetvis,\@vismsgs); + } + 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); + $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); +} + +sub cat_visibility { + my %visactions = &Apache::lonlocal::texthash( + vis => 'This 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 => 'This course/community does not currently appear in the Course/Community Catalog for this domain.', + none => 'Display of a course catalog is disabled for this domain.', + yous => 'You should remedy this if you plan to allow self-enrollment, otherwise students will have difficulty finding this 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_chgconf => 'Ask a domain coordinator to change the Catalog type for this domain.', + dc_setcode => 'Ask a domain coordinator to assign a six character code to the course', + 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.','"','"'); + return \%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,$readonly) = @_; + my $output; + my $numinrow = 4; + my $count = 0; + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($currdom); + my $othervalue = 'any'; + my $disabled; + if ($readonly) { + $disabled = ' disabled="disabled"'; + } + 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,$brcrum) = @_; + my $formname = 'rolelog'; + my ($username,$domain,$crstype,$viewablesec,%roleslog); + if ($context eq 'domain') { + $domain = $env{'request.role.domain'}; + %roleslog=&Apache::lonnet::dump_dom('nohist_rolelog',$domain); + } else { + if ($context eq 'course') { + $domain = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $username = $env{'course.'.$env{'request.course.id'}.'.num'}; + $crstype = &Apache::loncommon::course_type(); + $viewablesec = &Apache::lonuserutils::viewable_section($permission); + my %saveable_parameters = ('show' => 'scalar',); + &Apache::loncommon::store_course_settings('roles_log', + \%saveable_parameters); + &Apache::loncommon::restore_course_settings('roles_log', + \%saveable_parameters); + } elsif ($context eq 'author') { + $domain = $env{'user.domain'}; + if ($env{'request.role'} =~ m{^au\./\Q$domain\E/$}) { + $username = $env{'user.name'}; + } else { + undef($domain); + } + } + if ($domain ne '' && $username ne '') { + %roleslog=&Apache::lonnet::dump('nohist_rolelog',$domain,$username); + } + } + if ((keys(%roleslog))[0]=~/^error\:/) { undef(%roleslog); } + + my $helpitem; + if ($context eq 'course') { + $helpitem = 'Course_User_Logs'; + } elsif ($context eq 'domain') { + $helpitem = 'Domain_Role_Logs'; + } elsif ($context eq 'author') { + $helpitem = 'Author_User_Logs'; + } + push (@{$brcrum}, + {href => '/adm/createuser?action=changelogs', + text => 'User Management Logs', + help => $helpitem}); + my $bread_crumbs_component = 'User Changes'; + my $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + + # Create navigation javascript + my $jsnav = &userlogdisplay_js($formname); + + my $jscript = (< +// + +ENDSCRIPT + + # print page header + $r->print(&header($jscript,$args)); + + # 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'} =~ /\D/) { + $curr{'page'} = 1; + } else { + $maxshown = $curr{'page'} * $curr{'show'}; + if ($curr{'page'} > 1) { + $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'}; + } + } + + # Form Header + $r->print('
'. + &role_display_filter($context,$formname,$domain,$username,\%curr, + $version,$crstype)); + + 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').''; + + if ($context eq 'course') { + $tableheader .= ''.&mt('Section').''; + } + $tableheader .= + ''.&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'} !~ /\D/) { + 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'}); + } + } + if (($context eq 'course') && ($viewablesec ne '')) { + next if ($roleslog{$id}{'logentry'}{'section'} ne $viewablesec); + } + $count ++; + next if ($count < $minshown); + unless ($showntableheader) { + $r->print(&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($context,$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).''); + if ($context eq 'course') { + $r->print(''.$sec.''); + } + $r->print( + ''.$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(). + &userlogdisplay_navlinks(\%curr,$more_records)); + } else { # No content displayed above + $r->print('

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

' + ); + } + + # Form Footer + $r->print( + '' + .'' + .'
'); + return; +} + +sub print_useraccesslogs_display { + my ($r,$uname,$udom,$permission,$brcrum) = @_; + my $formname = 'accesslog'; + my $form = 'document.accesslog'; + +# set breadcrumbs + my %breadcrumb_text = &singleuser_breadcrumb('','domain',$udom); + my $prevphasestr; + if ($env{'form.popup'}) { + $brcrum = []; + } else { + push (@{$brcrum}, + {href => "javascript:backPage($form)", + text => $breadcrumb_text{'search'}}); + my @prevphases; + if ($env{'form.prevphases'}) { + @prevphases = split(/,/,$env{'form.prevphases'}); + $prevphasestr = $env{'form.prevphases'}; + } + if (($env{'form.phase'} eq 'userpicked') || (grep(/^userpicked$/,@prevphases))) { + push(@{$brcrum}, + {href => "javascript:backPage($form,'get_user_info','select')", + text => $breadcrumb_text{'userpicked'}}); + if ($env{'form.phase'} eq 'userpicked') { + $prevphasestr = 'userpicked'; + } + } + } + push(@{$brcrum}, + {href => '/adm/createuser?action=accesslogs', + text => 'User access logs', + help => 'Domain_User_Access_Logs'}); + my $bread_crumbs_component = 'User Access Logs'; + my $args = { bread_crumbs => $brcrum, + bread_crumbs_component => 'User Management'}; + if ($env{'form.popup'}) { + $args->{'no_nav_bar'} = 1; + $args->{'bread_crumbs_nomenu'} = 1; + } + +# set javascript + my ($jsback,$elements) = &crumb_utilities(); + my $jsnav = &userlogdisplay_js($formname); + + my $jscript = (< +// + + +ENDSCRIPT + +# print page header + $r->print(&header($jscript,$args)); + +# early out unless log data can be displayed. + unless ($permission->{'activity'}) { + $r->print('

' + .&mt('You do not have rights to display user access logs.') + .'

'); + if ($env{'form.popup'}) { + $r->print('

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

'); + } else { + $r->print(&earlyout_accesslog_form($formname,$prevphasestr,$udom)); + } + return; + } + + unless ($udom eq $env{'request.role.domain'}) { + $r->print('

' + .&mt("User's domain must match role's domain") + .'

' + .&earlyout_accesslog_form($formname,$prevphasestr,$udom)); + return; + } + + if (($uname eq '') || ($udom eq '')) { + $r->print('

' + .&mt('Invalid username or domain') + .'

' + .&earlyout_accesslog_form($formname,$prevphasestr,$udom)); + return; + } + + if (&Apache::lonnet::privileged($uname,$udom, + [$env{'request.role.domain'}],['dc','su'])) { + unless (&Apache::lonnet::privileged($env{'user.name'},$env{'user.domain'}, + [$env{'request.role.domain'}],['dc','su'])) { + $r->print('

' + .&mt('You need to be a privileged user to display user access logs for [_1]', + &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom), + $uname,$udom)) + .'

'); + if ($env{'form.popup'}) { + $r->print('

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

'); + } else { + $r->print(&earlyout_accesslog_form($formname,$prevphasestr,$udom)); + } + return; + } + } + +# set defaults + my $now = time(); + my $defstart = $now - (7*24*3600); + my %defaults = ( + page => '1', + show => '10', + activity => 'any', + accesslog_start_date => $defstart, + accesslog_end_date => $now, + ); + my $more_records = 0; + +# set current + my %curr; + foreach my $item ('show','page','activity') { + $curr{$item} = $env{'form.'.$item}; + } + my ($startdate,$enddate) = + &Apache::lonuserutils::get_dates_from_form('accesslog_start_date','accesslog_end_date'); + $curr{'accesslog_start_date'} = $startdate; + $curr{'accesslog_end_date'} = $enddate; + foreach my $key (keys(%defaults)) { + if ($curr{$key} eq '') { + $curr{$key} = $defaults{$key}; + } + } + my ($minshown,$maxshown); + $minshown = 1; + my $count = 0; + if ($curr{'show'} =~ /\D/) { + $curr{'page'} = 1; + } else { + $maxshown = $curr{'page'} * $curr{'show'}; + if ($curr{'page'} > 1) { + $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'}; + } + } + +# form header + $r->print('
'. + &activity_display_filter($formname,\%curr)); + + my $showntableheader = 0; + my ($nav_script,$nav_links); + +# table header + my $heading = '

'. + &mt('User access logs for: [_1]', + &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom),$uname,$udom)).'

'; + my $tableheader = $heading + .&Apache::loncommon::start_data_table_header_row() + .' ' + .''.&mt('When').'' + .''.&mt('HostID').'' + .''.&mt('Event').'' + .''.&mt('Other data').'' + .&Apache::loncommon::end_data_table_header_row(); + + my %filters=( + start => $curr{'accesslog_start_date'}, + end => $curr{'accesslog_end_date'}, + action => $curr{'activity'}, + ); + + my $reply = &Apache::lonnet::userlog_query($uname,$udom,%filters); + unless ( ($reply =~/^timeout/) || ($reply =~/^error/) ) { + my (%courses,%missing); + my @results = split(/\&/,$reply); + foreach my $item (reverse(@results)) { + my ($timestamp,$host,$event) = split(/:/,$item); + next unless ($event =~ /^(Log|Role)/); + if ($curr{'show'} !~ /\D/) { + if ($count >= $curr{'page'} * $curr{'show'}) { + $more_records = 1; + last; + } + } + $count ++; + next if ($count < $minshown); + unless ($showntableheader) { + $r->print($nav_script + .&Apache::loncommon::start_data_table() + .$tableheader); + $r->rflush(); + $showntableheader = 1; + } + my ($shown,$extra); + my ($event,$data) = split(/\s+/,&unescape($event),2); + if ($event eq 'Role') { + my ($rolecode,$extent) = split(/\./,$data,2); + next if ($extent eq ''); + my ($crstype,$desc,$info); + if ($extent =~ m{^/($match_domain)/($match_courseid)(?:/(\w+)|)$}) { + my ($cdom,$cnum,$sec) = ($1,$2,$3); + my $cid = $cdom.'_'.$cnum; + if (exists($courses{$cid})) { + $crstype = $courses{$cid}{'type'}; + $desc = $courses{$cid}{'description'}; + } elsif ($missing{$cid}) { + $crstype = 'Course'; + $desc = 'Course/Community'; + } else { + my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.'); + if (ref($crsinfo{$cdom.'_'.$cnum}) eq 'HASH') { + $courses{$cid} = $crsinfo{$cid}; + $crstype = $crsinfo{$cid}{'type'}; + $desc = $crsinfo{$cid}{'description'}; + } else { + $missing{$cid} = 1; + } + } + $extra = &mt($crstype).': '.$desc.''; + if ($sec ne '') { + $extra .= ' ('.&mt('Section: [_1]',$sec).')'; + } + } elsif ($extent =~ m{^/($match_domain)/($match_username|$)}) { + my ($dom,$name) = ($1,$2); + if ($rolecode eq 'au') { + $extra = ''; + } elsif ($rolecode =~ /^(ca|aa)$/) { + $extra = &mt('Authoring Space: [_1]',$name.':'.$dom); + } elsif ($rolecode =~ /^(li|dg|dh|dc|sc)$/) { + $extra = &mt('Domain: [_1]',$dom); + } + } + my $rolename; + if ($rolecode =~ m{^cr/($match_domain)/($match_username)/(\w+)}) { + my $role = $3; + my $owner = "($2:$1)"; + if ($2 eq $1.'-domainconfig') { + $owner = '(ad hoc)'; + } + $rolename = &mt('Custom role: [_1]',$role.' '.$owner); + } else { + $rolename = &Apache::lonnet::plaintext($rolecode,$crstype); + } + $shown = &mt('Role selection: [_1]',$rolename); + } else { + $shown = &mt($event); + if ($data =~ /^webdav/) { + my ($path,$clientip) = split(/\s+/,$data,2); + $path =~ s/^webdav//; + if ($clientip ne '') { + $extra = &mt('Client IP address: [_1]',$clientip); + } + if ($path ne '') { + $shown .= ' '.&mt('(WebDAV access to [_1])',$path); + } + } elsif ($data ne '') { + $extra = &mt('Client IP address: [_1]',$data); + } + } + $r->print( + &Apache::loncommon::start_data_table_row() + .''.$count.'' + .''.&Apache::lonlocal::locallocaltime($timestamp).'' + .''.$host.'' + .''.$shown.'' + .''.$extra.'' + .&Apache::loncommon::end_data_table_row()."\n"); + } + } + + if ($showntableheader) { # Table footer, if content displayed above + $r->print(&Apache::loncommon::end_data_table(). + &userlogdisplay_navlinks(\%curr,$more_records)); + } else { # No content displayed above + $r->print($heading.'

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

'); + } + + if ($env{'form.popup'} == 1) { + $r->print(''."\n"); + } + + # Form Footer + $r->print( + '' + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .'
'); + return; +} + +sub earlyout_accesslog_form { + my ($formname,$prevphasestr,$udom) = @_; + my $srchterm = &HTML::Entities::encode($env{'form.srchterm'},'<>"&'); + return <<"END"; +
+ + + + + + + + + +
+END +} + +sub activity_display_filter { + my ($formname,$curr) = @_; + my $nolink = 1; + my $output = ''; + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'accesslog_start_date', + $curr->{'accesslog_start_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'accesslog_end_date', + $curr->{'accesslog_end_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + my %lt = &Apache::lonlocal::texthash ( + activity => 'Activity', + Role => 'Role selection', + log => 'Log-in or Logout', + ); + $output .= ''. + ''. + ''. + '
'. + ''.&mt('Actions/page:').'
'. + &Apache::lonmeta::selectbox('show',$curr->{'show'},undef, + (&mt('all'),5,10,20,50,100,1000,10000)). + '
  '.&mt('Window during which actions occurred:').'
'. + ''. + ''. + '
'.&mt('After:'). + ''.$startform.'
'.&mt('Before:').''.$endform.'
'. + '
  '.&mt('Activities').'
'. + '
'; + # Update Display button + $output .= '

' + .'' + .'


'; + return $output; +} + +sub userlogdisplay_js { + my ($formname) = @_; + return <<"ENDSCRIPT"; + +function chgPage(caller) { + if (caller == 'previous') { + document.$formname.page.value --; + } + if (caller == 'next') { + document.$formname.page.value ++; + } + document.$formname.submit(); + return; +} +ENDSCRIPT +} + +sub userlogdisplay_navlinks { + my ($curr,$more_records) = @_; + return unless(ref($curr) eq 'HASH'); + # Navigation Buttons + my $nav_links = '

'; + if (($curr->{'page'} > 1) || ($more_records)) { + if (($curr->{'page'} > 1) && ($curr->{'show'} !~ /\D/)) { + $nav_links .= ' '; + } + if ($more_records) { + $nav_links .= ''; + } + } + $nav_links .= '

'; + return $nav_links; +} + +sub role_display_filter { + my ($context,$formname,$cdom,$cnum,$curr,$version,$crstype) = @_; + my $lctype; + if ($context eq 'course') { + $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($context,$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 + my $needsrev = '2.11.0'; + if ($context eq 'course') { + $needsrev = '2.7.0'; + } + + $output .= '

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


'; + return $output; +} + +sub rolechg_contexts { + my ($context,$crstype) = @_; + my %lt; + if ($context eq 'course') { + %lt = &Apache::lonlocal::texthash ( + any => 'Any', + automated => 'Automated Enrollment', + chgtype => 'Enrollment Type/Lock Change', + 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'); + } + } elsif ($context eq 'domain') { + %lt = &Apache::lonlocal::texthash ( + any => 'Any', + domain => 'User Management in domain', + requestauthor => 'Authoring Request', + server => 'Command line script (DC role)', + domconfig => 'Self-enrolled', + ); + } else { + %lt = &Apache::lonlocal::texthash ( + any => 'Any', + domain => 'User Management in domain', + author => 'User Management by author', + ); + } + return %lt; +} + +sub print_helpdeskaccess_display { + my ($r,$permission,$brcrum) = @_; + my $formname = 'helpdeskaccess'; + my $helpitem = 'Course_Helpdesk_Access'; + push (@{$brcrum}, + {href => '/adm/createuser?action=helpdesk', + text => 'Helpdesk Access', + help => $helpitem}); + my $bread_crumbs_component = 'Helpdesk Staff Access'; + my $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $confname = $cdom.'-domainconfig'; + my $crstype = &Apache::loncommon::course_type(); + + my @accesstypes = ('all','dh','da','none'); + my ($numstatustypes,@jsarray); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($cdom); + if (ref($types) eq 'ARRAY') { + if (@{$types} > 0) { + $numstatustypes = scalar(@{$types}); + push(@accesstypes,'status'); + @jsarray = ('bystatus'); + } + } + my %customroles = &get_domain_customroles($cdom,$confname); + my %domhelpdesk = &Apache::lonnet::get_active_domroles($cdom,['dh','da']); + if (keys(%domhelpdesk)) { + push(@accesstypes,('inc','exc')); + push(@jsarray,('notinc','notexc')); + } + push(@jsarray,'privs'); + my $hiddenstr = join("','",@jsarray); + my $rolestr = join("','",sort(keys(%customroles))); + + my $jscript; + my (%settings,%overridden); + if (keys(%customroles)) { + &get_adhocrole_settings($env{'request.course.id'},\@accesstypes, + $types,\%customroles,\%settings,\%overridden); + my %jsfull=(); + my %jslevels= ( + course => {}, + domain => {}, + system => {}, + ); + my %jslevelscurrent=( + course => {}, + domain => {}, + system => {}, + ); + my (%privs,%jsprivs); + &Apache::lonuserutils::custom_role_privs(\%privs,\%jsfull,\%jslevels,\%jslevelscurrent); + foreach my $priv (keys(%jsfull)) { + if ($jslevels{'course'}{$priv}) { + $jsprivs{$priv} = 1; + } + } + my (%elements,%stored); + foreach my $role (keys(%customroles)) { + $elements{$role.'_access'} = 'radio'; + $elements{$role.'_incrs'} = 'radio'; + if ($numstatustypes) { + $elements{$role.'_status'} = 'checkbox'; + } + if (keys(%domhelpdesk) > 0) { + $elements{$role.'_staff_inc'} = 'checkbox'; + $elements{$role.'_staff_exc'} = 'checkbox'; + } + $elements{$role.'_override'} = 'checkbox'; + if (ref($settings{$role}) eq 'HASH') { + if ($settings{$role}{'access'} ne '') { + my $curraccess = $settings{$role}{'access'}; + $stored{$role.'_access'} = $curraccess; + $stored{$role.'_incrs'} = 1; + if ($curraccess eq 'status') { + if (ref($settings{$role}{'status'}) eq 'ARRAY') { + $stored{$role.'_status'} = $settings{$role}{'status'}; + } + } elsif (($curraccess eq 'exc') || ($curraccess eq 'inc')) { + if (ref($settings{$role}{$curraccess}) eq 'ARRAY') { + $stored{$role.'_staff_'.$curraccess} = $settings{$role}{$curraccess}; + } + } + } else { + $stored{$role.'_incrs'} = 0; + } + $stored{$role.'_override'} = []; + if ($env{'course.'.$env{'request.course.id'}.'.internal.adhocpriv.'.$role}) { + if (ref($settings{$role}{'off'}) eq 'ARRAY') { + foreach my $priv (@{$settings{$role}{'off'}}) { + push(@{$stored{$role.'_override'}},$priv); + } + } + if (ref($settings{$role}{'on'}) eq 'ARRAY') { + foreach my $priv (@{$settings{$role}{'on'}}) { + unless (grep(/^$priv$/,@{$stored{$role.'_override'}})) { + push(@{$stored{$role.'_override'}},$priv); + } + } + } + } + } else { + $stored{$role.'_incrs'} = 0; + } + } + $jscript = &Apache::lonhtmlcommon::set_form_elements(\%elements,\%stored); + } + + my $js = <<"ENDJS"; + +ENDJS + + $args->{add_entries} = {onload => "javascript:setFormElements(document.$formname)"}; + + # print page header + $r->print(&header($js,$args)); + # print form header + $r->print('
'); + + if (keys(%customroles)) { + my %lt = &Apache::lonlocal::texthash( + 'aco' => 'As course owner you may override the defaults set in the domain for role usage and/or privileges.', + 'rou' => 'Role usage', + 'whi' => 'Which helpdesk personnel may use this role?', + 'udd' => 'Use domain default', + 'all' => 'All with domain helpdesk or helpdesk assistant role', + 'dh' => 'All with domain helpdesk role', + 'da' => 'All with domain helpdesk assistant role', + 'none' => 'None', + 'status' => 'Determined based on institutional status', + 'inc' => 'Include all, but exclude specific personnel', + 'exc' => 'Exclude all, but include specific personnel', + 'hel' => 'Helpdesk', + 'rpr' => 'Role privileges', + ); + $lt{'tfh'} = &mt("Custom [_1]ad hoc[_2] course roles available for use by the domain's helpdesk are as follows",'',''); + my %domconfig = &Apache::lonnet::get_dom('configuration',['helpsettings'],$cdom); + my (%domcurrent,%ordered,%description,%domusage,$disabled); + if (ref($domconfig{'helpsettings'}) eq 'HASH') { + if (ref($domconfig{'helpsettings'}{'adhoc'}) eq 'HASH') { + %domcurrent = %{$domconfig{'helpsettings'}{'adhoc'}}; + } + } + my $count = 0; + foreach my $role (sort(keys(%customroles))) { + my ($order,$desc,$access_in_dom); + if (ref($domcurrent{$role}) eq 'HASH') { + $order = $domcurrent{$role}{'order'}; + $desc = $domcurrent{$role}{'desc'}; + $access_in_dom = $domcurrent{$role}{'access'}; + } + if ($order eq '') { + $order = $count; + } + $ordered{$order} = $role; + if ($desc ne '') { + $description{$role} = $desc; + } else { + $description{$role}= $role; + } + $count++; + } + %domusage = &domain_adhoc_access(\%customroles,\%domcurrent,\@accesstypes,$usertypes,$othertitle); + my @roles_by_num = (); + foreach my $item (sort {$a <=> $b } (keys(%ordered))) { + push(@roles_by_num,$ordered{$item}); + } + $r->print('

'.$lt{'tfh'}.': '.join(', ',map { $description{$_}; } @roles_by_num).'.'); + if ($permission->{'owner'}) { + $r->print('
'.$lt{'aco'}.'

'); + $r->print(''. + ''); + } else { + if ($env{'course.'.$env{'request.course.id'}.'.internal.courseowner'}) { + my ($ownername,$ownerdom) = split(/:/,$env{'course.'.$env{'request.course.id'}.'.internal.courseowner'}); + $r->print('
'.&mt('The course owner -- [_1] -- can override the default access and/or privileges for these ad hoc roles.', + &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($ownername,$ownerdom),$ownername,$ownerdom))); + } + $disabled = ' disabled="disabled"'; + } + $r->print('

'); + + $r->print('
    '); + my $count = 0; + my %visibility; + foreach my $role (@roles_by_num) { + my $id; + if ($count == 0) { + $id=' id="LC_current_minitab"'; + $visibility{$role} = ' style="display:block"'; + } else { + $visibility{$role} = ' style="display:none"'; + } + $count ++; + $r->print(''.$description{$role}.''); + } + $r->print('
'); + + foreach my $role (@roles_by_num) { + my %usecheck = ( + all => ' checked="checked"', + ); + my %displaydiv = ( + status => 'none', + inc => 'none', + exc => 'none', + priv => 'block', + ); + my (%selected,$overridden,$incrscheck,$indomcheck,$indomvis,$incrsvis); + if (ref($settings{$role}) eq 'HASH') { + if ($settings{$role}{'access'} ne '') { + $indomvis = ' style="display:none"'; + $incrsvis = ' style="display:block"'; + $incrscheck = ' checked="checked"'; + if ($settings{$role}{'access'} ne 'all') { + $usecheck{$settings{$role}{'access'}} = $usecheck{'all'}; + delete($usecheck{'all'}); + if ($settings{$role}{'access'} eq 'status') { + my $access = 'status'; + $displaydiv{$access} = 'inline'; + if (ref($settings{$role}{$access}) eq 'ARRAY') { + $selected{$access} = $settings{$role}{$access}; + } + } elsif ($settings{$role}{'access'} =~ /^(inc|exc)$/) { + my $access = $1; + $displaydiv{$access} = 'inline'; + if (ref($settings{$role}{$access}) eq 'ARRAY') { + $selected{$access} = $settings{$role}{$access}; + } + } elsif ($settings{$role}{'access'} eq 'none') { + $displaydiv{'priv'} = 'none'; + } + } + } else { + $indomcheck = ' checked="checked"'; + $indomvis = ' style="display:block"'; + $incrsvis = ' style="display:none"'; + } + } else { + $indomcheck = ' checked="checked"'; + $indomvis = ' style="display:block"'; + $incrsvis = ' style="display:none"'; + } + $r->print('
'. + '
'.$lt{'rou'}.''. + '

'.$lt{'whi'}.' '. + ''. + ''.(' 'x2). + '

'. + '
'. + ''.$domusage{$role}.'
'. + '
'); + foreach my $access (@accesstypes) { + $r->print('

'); + if ($access eq 'status') { + $r->print('

'. + &Apache::lonuserutils::adhoc_status_types($cdom,undef,$role,$selected{$access}, + $othertitle,$usertypes,$types,$disabled). + '
'); + } elsif (($access eq 'inc') && (keys(%domhelpdesk) > 0)) { + $r->print('
'. + &Apache::lonuserutils::adhoc_staff($access,undef,$role,$selected{$access}, + \%domhelpdesk,$disabled). + '
'); + } elsif (($access eq 'exc') && (keys(%domhelpdesk) > 0)) { + $r->print('
'. + &Apache::lonuserutils::adhoc_staff($access,undef,$role,$selected{$access}, + \%domhelpdesk,$disabled). + '
'); + } + $r->print('

'); + } + $r->print('
'); + my %full=(); + my %levels= ( + course => {}, + domain => {}, + system => {}, + ); + my %levelscurrent=( + course => {}, + domain => {}, + system => {}, + ); + &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent); + $r->print('
'. + ''.$lt{'rpr'}.''. + &role_priv_table($role,$permission,$crstype,\%full,\%levels,\%levelscurrent,$overridden{$role}). + '
'); + } + if ($permission->{'owner'}) { + $r->print('

'); + } + } else { + $r->print(&mt('Helpdesk roles have not yet been created in this domain.')); + } + # Form Footer + $r->print('' + .'
'); + return; +} + +sub domain_adhoc_access { + my ($roles,$domcurrent,$accesstypes,$usertypes,$othertitle) = @_; + my %domusage; + return unless ((ref($roles) eq 'HASH') && (ref($domcurrent) eq 'HASH') && (ref($accesstypes) eq 'ARRAY')); + foreach my $role (keys(%{$roles})) { + if (ref($domcurrent->{$role}) eq 'HASH') { + my $access = $domcurrent->{$role}{'access'}; + if (($access eq '') || (!grep(/^\Q$access\E$/,@{$accesstypes}))) { + $access = 'all'; + $domusage{$role} = &mt('Any user in domain with active [_1] or [_2] role',&Apache::lonnet::plaintext('dh'), + &Apache::lonnet::plaintext('da')); + } elsif ($access eq 'status') { + if (ref($domcurrent->{$role}{$access}) eq 'ARRAY') { + my @shown; + foreach my $type (@{$domcurrent->{$role}{$access}}) { + unless ($type eq 'default') { + if ($usertypes->{$type}) { + push(@shown,$usertypes->{$type}); + } + } + } + if (grep(/^default$/,@{$domcurrent->{$role}{$access}})) { + push(@shown,$othertitle); + } + if (@shown) { + my $shownstatus = join(' '.&mt('or').' ',@shown); + $domusage{$role} = &mt('Any user in domain with active [_1] or [_2] role, and institutional status: [_3]', + &Apache::lonnet::plaintext('dh'),&Apache::lonnet::plaintext('da'),$shownstatus); + } else { + $domusage{$role} = &mt('No one in the domain'); + } + } + } elsif ($access eq 'inc') { + my @dominc = (); + if (ref($domcurrent->{$role}{'inc'}) eq 'ARRAY') { + foreach my $user (@{$domcurrent->{$role}{'inc'}}) { + my ($uname,$udom) = split(/:/,$user); + push(@dominc,&Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom),$uname,$udom)); + } + my $showninc = join(', ',@dominc); + if ($showninc ne '') { + $domusage{$role} = &mt('Include any user in domain with active [_1] or [_2] role, except: [_3]', + &Apache::lonnet::plaintext('dh'),&Apache::lonnet::plaintext('da'),$showninc); + } else { + $domusage{$role} = &mt('Any user in domain with active [_1] or [_2] role', + &Apache::lonnet::plaintext('dh'),&Apache::lonnet::plaintext('da')); + } + } + } elsif ($access eq 'exc') { + my @domexc = (); + if (ref($domcurrent->{$role}{'exc'}) eq 'ARRAY') { + foreach my $user (@{$domcurrent->{$role}{'exc'}}) { + my ($uname,$udom) = split(/:/,$user); + push(@domexc,&Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom),$uname,$udom)); + } + } + my $shownexc = join(', ',@domexc); + if ($shownexc ne '') { + $domusage{$role} = &mt('Only the following in the domain with active [_1] or [_2] role: [_3]', + &Apache::lonnet::plaintext('dh'),&Apache::lonnet::plaintext('da'),$shownexc); + } else { + $domusage{$role} = &mt('No one in the domain'); + } + } elsif ($access eq 'none') { + $domusage{$role} = &mt('No one in the domain'); + } elsif ($access eq 'dh') { + $domusage{$role} = &mt('Any user in domain with active [_1] role',&Apache::lonnet::plaintext('dh')); + } elsif ($access eq 'da') { + $domusage{$role} = &mt('Any user in domain with active [_1] role',&Apache::lonnet::plaintext('da')); + } elsif ($access eq 'all') { + $domusage{$role} = &mt('Any user in domain with active [_1] or [_2] role', + &Apache::lonnet::plaintext('dh'),&Apache::lonnet::plaintext('da')); + } + } else { + $domusage{$role} = &mt('Any user in domain with active [_1] or [_2] role', + &Apache::lonnet::plaintext('dh'),&Apache::lonnet::plaintext('da')); + } + } + return %domusage; +} + +sub get_domain_customroles { + my ($cdom,$confname) = @_; + my %existing=&Apache::lonnet::dump('roles',$cdom,$confname,'rolesdef_'); + my %customroles; + foreach my $key (keys(%existing)) { + if ($key=~/^rolesdef\_(\w+)$/) { + my $rolename = $1; + my %privs; + ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key}); + $customroles{$rolename} = \%privs; + } + } + return %customroles; +} + +sub role_priv_table { + my ($role,$permission,$crstype,$full,$levels,$levelscurrent,$overridden) = @_; + return unless ((ref($full) eq 'HASH') && (ref($levels) eq 'HASH') && + (ref($levelscurrent) eq 'HASH')); + my %lt=&Apache::lonlocal::texthash ( + 'crl' => 'Course Level Privilege', + 'def' => 'Domain Defaults', + 'ove' => 'Override in Course', + 'ine' => 'In effect', + 'dis' => 'Disabled', + 'ena' => 'Enabled', + ); + if ($crstype eq 'Community') { + $lt{'ove'} = 'Override in Community', + } + my @status = ('Disabled','Enabled'); + my (%on,%off); + if (ref($overridden) eq 'HASH') { + if (ref($overridden->{'on'}) eq 'ARRAY') { + map { $on{$_} = 1; } (@{$overridden->{'on'}}); + } + if (ref($overridden->{'off'}) eq 'ARRAY') { + map { $off{$_} = 1; } (@{$overridden->{'off'}}); + } + } + my $output=&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ''.$lt{'crl'}.''.$lt{'def'}.''.$lt{'ove'}. + ''.$lt{'ine'}.''. + &Apache::loncommon::end_data_table_header_row(); + foreach my $priv (sort(keys(%{$full}))) { + next unless ($levels->{'course'}{$priv}); + my $privtext = &Apache::lonnet::plaintext($priv,$crstype); + my ($default,$ineffect); + if ($levelscurrent->{'course'}{$priv}) { + $default = ''.$lt{'ena'}.''; + $ineffect = $default; + } + my ($customstatus,$checked); + $output .= &Apache::loncommon::start_data_table_row(). + ''.$privtext.''. + ''.$default.''; + if (($levelscurrent->{'course'}{$priv}) && ($off{$priv})) { + if ($permission->{'owner'}) { + $checked = ' checked="checked"'; + } + $customstatus = ''.$lt{'dis'}.''; + $ineffect = $customstatus; + } elsif ((!$levelscurrent->{'course'}{$priv}) && ($on{$priv})) { + if ($permission->{'owner'}) { + $checked = ' checked="checked"'; + } + $customstatus = ''.$lt{'ena'}.''; + $ineffect = $customstatus; + } + if ($permission->{'owner'}) { + $output .= ''; + } else { + $output .= $customstatus; + } + $output .= ''.$ineffect.''. + &Apache::loncommon::end_data_table_row(); + } + $output .= &Apache::loncommon::end_data_table(); + return $output; +} + +sub get_adhocrole_settings { + my ($cid,$accesstypes,$types,$customroles,$settings,$overridden) = @_; + return unless ((ref($accesstypes) eq 'ARRAY') && (ref($customroles) eq 'HASH') && + (ref($settings) eq 'HASH') && (ref($overridden) eq 'HASH')); + foreach my $role (split(/,/,$env{'course.'.$cid.'.internal.adhocaccess'})) { + my ($curraccess,$rest) = split(/=/,$env{'course.'.$cid.'.internal.adhoc.'.$role}); + if (($curraccess ne '') && (grep(/^\Q$curraccess\E$/,@{$accesstypes}))) { + $settings->{$role}{'access'} = $curraccess; + if (($curraccess eq 'status') && (ref($types) eq 'ARRAY')) { + my @status = split(/,/,$rest); + my @currstatus; + foreach my $type (@status) { + if ($type eq 'default') { + push(@currstatus,$type); + } elsif (grep(/^\Q$type\E$/,@{$types})) { + push(@currstatus,$type); + } + } + if (@currstatus) { + $settings->{$role}{$curraccess} = \@currstatus; + } elsif (($curraccess eq 'exc') || ($curraccess eq 'inc')) { + my @personnel = split(/,/,$rest); + $settings->{$role}{$curraccess} = \@personnel; + } + } + } + } + foreach my $role (keys(%{$customroles})) { + if ($env{'course.'.$cid.'.internal.adhocpriv.'.$role}) { + my %currentprivs; + if (ref($customroles->{$role}) eq 'HASH') { + if (exists($customroles->{$role}{'course'})) { + my %full=(); + my %levels= ( + course => {}, + domain => {}, + system => {}, + ); + my %levelscurrent=( + course => {}, + domain => {}, + system => {}, + ); + &Apache::lonuserutils::custom_role_privs($customroles->{$role},\%full,\%levels,\%levelscurrent); + %currentprivs = %{$levelscurrent{'course'}}; + } + } + foreach my $item (split(/,/,$env{'course.'.$cid.'.internal.adhocpriv.'.$role})) { + next if ($item eq ''); + my ($rule,$rest) = split(/=/,$item); + next unless (($rule eq 'off') || ($rule eq 'on')); + foreach my $priv (split(/:/,$rest)) { + if ($priv ne '') { + if ($rule eq 'off') { + push(@{$overridden->{$role}{'off'}},$priv); + if ($currentprivs{$priv}) { + push(@{$settings->{$role}{'off'}},$priv); + } + } else { + push(@{$overridden->{$role}{'on'}},$priv); + unless ($currentprivs{$priv}) { + push(@{$settings->{$role}{'on'}},$priv); + } + } + } + } + } + } + } + return; +} + +sub update_helpdeskaccess { + my ($r,$permission,$brcrum) = @_; + my $helpitem = 'Course_Helpdesk_Access'; + push (@{$brcrum}, + {href => '/adm/createuser?action=helpdesk', + text => 'Helpdesk Access', + help => $helpitem}, + {href => '/adm/createuser?action=helpdesk', + text => 'Result', + help => $helpitem} + ); + my $bread_crumbs_component = 'Helpdesk Staff Access'; + my $args = { bread_crumbs => $brcrum, + bread_crumbs_component => $bread_crumbs_component}; + + # print page header + $r->print(&header('',$args)); + unless ((ref($permission) eq 'HASH') && ($permission->{'owner'})) { + $r->print('

'.&mt('You do not have permission to change helpdesk access.').'

'); + return; + } + my @accesstypes = ('all','dh','da','none','status','inc','exc'); + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $confname = $cdom.'-domainconfig'; + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($cdom); + my $crstype = &Apache::loncommon::course_type(); + my %customroles = &get_domain_customroles($cdom,$confname); + my (%settings,%overridden); + &get_adhocrole_settings($env{'request.course.id'},\@accesstypes, + $types,\%customroles,\%settings,\%overridden); + my %domhelpdesk = &Apache::lonnet::get_active_domroles($cdom,['dh','da']); + my (%changed,%storehash,@todelete); + + if (keys(%customroles)) { + my (%newsettings,@incrs); + foreach my $role (keys(%customroles)) { + $newsettings{$role} = { + access => '', + status => '', + exc => '', + inc => '', + on => '', + off => '', + }; + my %current; + if (ref($settings{$role}) eq 'HASH') { + %current = %{$settings{$role}}; + } + if (ref($overridden{$role}) eq 'HASH') { + $current{'overridden'} = $overridden{$role}; + } + if ($env{'form.'.$role.'_incrs'}) { + my $access = $env{'form.'.$role.'_access'}; + if (grep(/^\Q$access\E$/,@accesstypes)) { + push(@incrs,$role); + unless ($current{'access'} eq $access) { + $changed{$role}{'access'} = 1; + $storehash{'internal.adhoc.'.$role} = $access; + } + if ($access eq 'status') { + my @statuses = &Apache::loncommon::get_env_multiple('form.'.$role.'_status'); + my @stored; + my @shownstatus; + if (ref($types) eq 'ARRAY') { + foreach my $type (sort(@statuses)) { + if ($type eq 'default') { + push(@stored,$type); + } elsif (grep(/^\Q$type\E$/,@{$types})) { + push(@stored,$type); + push(@shownstatus,$usertypes->{$type}); + } + } + if (grep(/^default$/,@statuses)) { + push(@shownstatus,$othertitle); + } + $storehash{'internal.adhoc.'.$role} .= '='.join(',',@stored); + } + $newsettings{$role}{'status'} = join(' '.&mt('or').' ',@shownstatus); + if (ref($current{'status'}) eq 'ARRAY') { + my @diffs = &Apache::loncommon::compare_arrays(\@stored,$current{'status'}); + if (@diffs) { + $changed{$role}{'status'} = 1; + } + } elsif (@stored) { + $changed{$role}{'status'} = 1; + } + } elsif (($access eq 'inc') || ($access eq 'exc')) { + my @personnel = &Apache::loncommon::get_env_multiple('form.'.$role.'_staff_'.$access); + my @newspecstaff; + my @stored; + my @currstaff; + foreach my $person (sort(@personnel)) { + if ($domhelpdesk{$person}) { + push(@stored,$person); + } + } + if (ref($current{$access}) eq 'ARRAY') { + my @diffs = &Apache::loncommon::compare_arrays(\@stored,$current{$access}); + if (@diffs) { + $changed{$role}{$access} = 1; + } + } elsif (@stored) { + $changed{$role}{$access} = 1; + } + $storehash{'internal.adhoc.'.$role} .= '='.join(',',@stored); + foreach my $person (@stored) { + my ($uname,$udom) = split(/:/,$person); + push(@newspecstaff,&Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom,'lastname'),$uname,$udom)); + } + $newsettings{$role}{$access} = join(', ',sort(@newspecstaff)); + } + $newsettings{$role}{'access'} = $access; + } + } else { + if (($current{'access'} ne '') && (grep(/^\Q$current{'access'}\E$/,@accesstypes))) { + $changed{$role}{'access'} = 1; + $newsettings{$role} = {}; + push(@todelete,'internal.adhoc.'.$role); + } + } + if (($env{'form.'.$role.'_incrs'}) && ($env{'form.'.$role.'_access'} eq 'none')) { + if (ref($current{'overridden'}) eq 'HASH') { + push(@todelete,'internal.adhocpriv.'.$role); + } + } else { + my %full=(); + my %levels= ( + course => {}, + domain => {}, + system => {}, + ); + my %levelscurrent=( + course => {}, + domain => {}, + system => {}, + ); + &Apache::lonuserutils::custom_role_privs($customroles{$role},\%full,\%levels,\%levelscurrent); + my (@updatedon,@updatedoff,@override); + @override = &Apache::loncommon::get_env_multiple('form.'.$role.'_override'); + if (@override) { + foreach my $priv (sort(keys(%full))) { + next unless ($levels{'course'}{$priv}); + if (grep(/^\Q$priv\E$/,@override)) { + if ($levelscurrent{'course'}{$priv}) { + push(@updatedoff,$priv); + } else { + push(@updatedon,$priv); + } + } + } + } + if (@updatedon) { + $newsettings{$role}{'on'} = join('
  • ', map { &Apache::lonnet::plaintext($_,$crstype) } (@updatedon)); + } + if (@updatedoff) { + $newsettings{$role}{'off'} = join('
  • ', map { &Apache::lonnet::plaintext($_,$crstype) } (@updatedoff)); + } + if (ref($current{'overridden'}) eq 'HASH') { + if (ref($current{'overridden'}{'on'}) eq 'ARRAY') { + if (@updatedon) { + my @diffs = &Apache::loncommon::compare_arrays(\@updatedon,$current{'overridden'}{'on'}); + if (@diffs) { + $changed{$role}{'on'} = 1; + } + } else { + $changed{$role}{'on'} = 1; + } + } elsif (@updatedon) { + $changed{$role}{'on'} = 1; + } + if (ref($current{'overridden'}{'off'}) eq 'ARRAY') { + if (@updatedoff) { + my @diffs = &Apache::loncommon::compare_arrays(\@updatedoff,$current{'overridden'}{'off'}); + if (@diffs) { + $changed{$role}{'off'} = 1; + } + } else { + $changed{$role}{'off'} = 1; + } + } elsif (@updatedoff) { + $changed{$role}{'off'} = 1; + } + } else { + if (@updatedon) { + $changed{$role}{'on'} = 1; + } + if (@updatedoff) { + $changed{$role}{'off'} = 1; + } + } + if (ref($changed{$role}) eq 'HASH') { + if (($changed{$role}{'on'} || $changed{$role}{'off'})) { + my $newpriv; + if (@updatedon) { + $newpriv = 'on='.join(':',@updatedon); + } + if (@updatedoff) { + $newpriv .= ($newpriv ? ',' : '' ).'off='.join(':',@updatedoff); + } + if ($newpriv eq '') { + push(@todelete,'internal.adhocpriv.'.$role); + } else { + $storehash{'internal.adhocpriv.'.$role} = $newpriv; + } + } + } + } + } + if (@incrs) { + $storehash{'internal.adhocaccess'} = join(',',@incrs); + } elsif (@todelete) { + push(@todelete,'internal.adhocaccess'); + } + if (keys(%changed)) { + my ($putres,$delres); + if (keys(%storehash)) { + $putres = &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum); + my %newenvhash; + foreach my $key (keys(%storehash)) { + $newenvhash{'course.'.$env{'request.course.id'}.'.'.$key} = $storehash{$key}; + } + &Apache::lonnet::appenv(\%newenvhash); + } + if (@todelete) { + $delres = &Apache::lonnet::del('environment',\@todelete,$cdom,$cnum); + foreach my $key (@todelete) { + &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.'.$key); + } + } + if (($putres eq 'ok') || ($delres eq 'ok')) { + my %domconfig = &Apache::lonnet::get_dom('configuration',['helpsettings'],$cdom); + my (%domcurrent,%ordered,%description,%domusage); + if (ref($domconfig{'helpsettings'}) eq 'HASH') { + if (ref($domconfig{'helpsettings'}{'adhoc'}) eq 'HASH') { + %domcurrent = %{$domconfig{'helpsettings'}{'adhoc'}}; + } + } + my $count = 0; + foreach my $role (sort(keys(%customroles))) { + my ($order,$desc); + if (ref($domcurrent{$role}) eq 'HASH') { + $order = $domcurrent{$role}{'order'}; + $desc = $domcurrent{$role}{'desc'}; + } + if ($order eq '') { + $order = $count; + } + $ordered{$order} = $role; + if ($desc ne '') { + $description{$role} = $desc; + } else { + $description{$role}= $role; + } + $count++; + } + my @roles_by_num = (); + foreach my $item (sort {$a <=> $b } (keys(%ordered))) { + push(@roles_by_num,$ordered{$item}); + } + %domusage = &domain_adhoc_access(\%changed,\%domcurrent,\@accesstypes,$usertypes,$othertitle); + $r->print(&mt('Helpdesk access settings have been changed as follows').'
    '); + $r->print('
      '); + foreach my $role (@roles_by_num) { + next unless (ref($changed{$role}) eq 'HASH'); + $r->print('
    • '.&mt('Ad hoc role').': '.$description{$role}.''. + '
        '); + if ($changed{$role}{'access'} || $changed{$role}{'status'} || $changed{$role}{'inc'} || $changed{$role}{'exc'}) { + $r->print('
      • '); + if ($env{'form.'.$role.'_incrs'}) { + if ($newsettings{$role}{'access'} eq 'all') { + $r->print(&mt('All helpdesk staff can access '.lc($crstype).' with this role.')); + } elsif ($newsettings{$role}{'access'} eq 'dh') { + $r->print(&mt('Helpdesk staff can use this role if they have an active [_1] role', + &Apache::lonnet::plaintext('dh'))); + } elsif ($newsettings{$role}{'access'} eq 'da') { + $r->print(&mt('Helpdesk staff can use this role if they have an active [_1] role', + &Apache::lonnet::plaintext('da'))); + } elsif ($newsettings{$role}{'access'} eq 'none') { + $r->print(&mt('No helpdesk staff can access '.lc($crstype).' with this role.')); + } elsif ($newsettings{$role}{'access'} eq 'status') { + if ($newsettings{$role}{'status'}) { + my ($access,$rest) = split(/=/,$storehash{'internal.adhoc.'.$role}); + if (split(/,/,$rest) > 1) { + $r->print(&mt('Helpdesk staff can use this role if their institutional type is one of: [_1].', + $newsettings{$role}{'status'})); + } else { + $r->print(&mt('Helpdesk staff can use this role if their institutional type is: [_1].', + $newsettings{$role}{'status'})); + } + } else { + $r->print(&mt('No helpdesk staff can access '.lc($crstype).' with this role.')); + } + } elsif ($newsettings{$role}{'access'} eq 'exc') { + if ($newsettings{$role}{'exc'}) { + $r->print(&mt('Helpdesk staff who can use this role are as follows:').' '.$newsettings{$role}{'exc'}.'.'); + } else { + $r->print(&mt('No helpdesk staff can access '.lc($crstype).' with this role.')); + } + } elsif ($newsettings{$role}{'access'} eq 'inc') { + if ($newsettings{$role}{'inc'}) { + $r->print(&mt('All helpdesk staff may use this role except the following:').' '.$newsettings{$role}{'inc'}.'.'); + } else { + $r->print(&mt('All helpdesk staff may use this role.')); + } + } + } else { + $r->print(&mt('Default access set in the domain now applies.').'
        '. + ''.$domusage{$role}.''); + } + $r->print('
      • '); + } + unless ($newsettings{$role}{'access'} eq 'none') { + if ($changed{$role}{'off'}) { + if ($newsettings{$role}{'off'}) { + $r->print('
      • '.&mt('Privileges which are available by default for this ad hoc role, but are disabled for this specific '.lc($crstype).':'). + '
        • '.$newsettings{$role}{'off'}.'
      • '); + } else { + $r->print('
      • '.&mt('All privileges available by default for this ad hoc role are enabled.').'
      • '); + } + } + if ($changed{$role}{'on'}) { + if ($newsettings{$role}{'on'}) { + $r->print('
      • '.&mt('Privileges which are not available by default for this ad hoc role, but are enabled for this specific '.lc($crstype).':'). + '
        • '.$newsettings{$role}{'on'}.'
      • '); + } else { + $r->print('
      • '.&mt('None of the privileges unavailable by default for this ad hoc role are enabled.').'
      • '); + } + } + } + $r->print('
    • '); + } + $r->print('
    '); + } + } else { + $r->print(&mt('No changes made to helpdesk access settings.')); + } + } + return; +} + #-------------------------------------------------- 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 = &instdirectorysrch_check($srch); + if ($instd_chk ne 'ok') { + my $domd_chk = &domdirectorysrch_check($srch); + $response .= ''.$instd_chk.'
    '; + if ($domd_chk eq 'ok') { + $response .= &mt('You may want to search in the LON-CAPA domain instead of the institutional directory.'); + } + $response .= '
    '; + } + } else { + unless (($context eq 'requestcrs') && ($srch->{'srchtype'} eq 'exact')) { + my $domd_chk = &domdirectorysrch_check($srch); + if (($domd_chk ne 'ok') && ($env{'form.action'} ne 'accesslogs')) { + my $instd_chk = &instdirectorysrch_check($srch); + $response .= ''.$domd_chk.'
    '; + if ($instd_chk eq 'ok') { + $response .= &mt('You may want to search in the institutional directory instead of the LON-CAPA domain.'); + } + $response .= '
    '; + } + } + } + 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'; + if ($env{'form.action'} eq 'accesslogs') { + $currstate = 'activity'; + } + 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 domdirectorysrch_check { + my ($srch) = @_; + 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'}{'lcavailable'} eq '0') { + return &mt('LON-CAPA directory search is not available in domain: [_1]',$showdom); + } + if ($dom_inst_srch{'directorysrch'}{'lclocalonly'}) { + if ($env{'request.role.domain'} ne $srch->{'srchdomain'}) { + return &mt('LON-CAPA directory search in domain: [_1] is only allowed for users with a current role in the domain.',$showdom); + } + } + } + return 'ok'; +} + +sub instdirectorysrch_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) { + if ($env{'form.action'} eq 'accesslogs') { + $currstate = 'activity'; + } else { + $currstate = 'modify'; + } + $response = &mt("$single{$srch->{'srchtype'}} was found for the $names{$srch->{'srchby'}} ([_1]) in $names{$srch->{'srchin'}}.",$srch->{'srchterm'}); + if ($srch->{'srchin'} eq 'dom' || $srch->{'srchin'} eq 'instd') { + $response .= ': '.&display_domain_info($srch->{'srchdomain'}); + } + } 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'}) && ($env{'form.action'} ne 'accesslogs')) { + 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'}; + } + } + unless (($env{'form.action'} eq 'accesslogs') || (($srch->{'srchby'} eq 'uname') && ($srch->{'srchin'} eq 'dom') && + ($srch->{'srchtype'} eq 'exact') && ($srch->{'srchdomain'} eq $createdom))) { + my $cancreate = + &Apache::lonuserutils::can_create_user($createdom,$context); + my $targetdom = ''.$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 { + unless (($context eq 'domain') && ($env{'form.action'} eq 'singleuser')) { + 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 ($inccourses,$showcredits,$defaultcredits) = @_; + return unless (ref($inccourses) eq 'HASH'); my $table = ''; - foreach (sort( keys(%inccourses))) { - my $thiscourse=$_; - my $protectedcourse=$_; +# Custom Roles? + + my %customroles=&Apache::lonuserutils::my_custom_roles(); + my %lt=&Apache::lonlocal::texthash( + 'exs' => "Existing sections", + 'new' => "Define new section", + 'ssd' => "Set Start Date", + 'sed' => "Set End Date", + 'crl' => "Course Level", + 'act' => "Activate", + 'rol' => "Role", + 'ext' => "Extent", + 'grs' => "Section", + 'crd' => "Credits", + 'sta' => "Start", + 'end' => "End" + ); + + foreach my $protectedcourse (sort(keys(%{$inccourses}))) { + my $thiscourse=$protectedcourse; $thiscourse=~s:_:/:g; my %coursedata=&Apache::lonnet::coursedescription($thiscourse); + my $isowner = &Apache::lonuserutils::is_courseowner($protectedcourse,$coursedata{'internal.courseowner'}); my $area=$coursedata{'description'}; - my $bgcol=$thiscourse; - $bgcol=~s/[^8-9b-e]//g; - $bgcol=substr($bgcol.$bgcol.$bgcol.'ffffff',0,6); - foreach ('st','ta','ep','ad','in','cc') { - if (&Apache::lonnet::allowed('c'.$_,$thiscourse)) { - my $plrole=&Apache::lonnet::plaintext($_); - $table .= < - -$plrole -$area -ENDEXTENT - if ($_ ne 'cc') { - $table .= < -ENDSECTION - } else { - $table .= <  -ENDSECTION + my $crstype=$coursedata{'type'}; + if (!defined($area)) { $area=&mt('Unavailable course').': '.$protectedcourse; } + my ($domain,$cnum)=split(/\//,$thiscourse); + my %sections_count; + if (defined($env{'request.course.id'})) { + if ($env{'request.course.id'} eq $domain.'_'.$cnum) { + %sections_count = + &Apache::loncommon::get_sections($domain,$cnum); + } + } + 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, + $showcredits,$defaultcredits,$crstype); + } 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, + $showcredits,$defaultcredits,$crstype); } - $table .= < -Set Start Date - -Set End Date -ENDTIMEENTRY - $table.= "\n"; } } + 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, + $showcredits,$defaultcredits,$crstype); + } + } } return '' if ($table eq ''); # return nothing if there is nothing # in the table - my $result = <Course Level - - -$table -
    ActivateRoleExtentGroup/SectionStartEnd
    -ENDTABLE + 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'}.''."\n". +''.$lt{'ext'}.''."\n"; + if ($showcredits) { + $result .= $lt{'crd'}.''; + } + $result .= +''.$lt{'grs'}.''.$lt{'sta'}.''."\n". +''.$lt{'end'}.''. +&Apache::loncommon::end_data_table_header_row(). +$table. +&Apache::loncommon::end_data_table(); return $result; } + +sub course_level_row { + my ($protectedcourse,$role,$area,$domain,$plrole,$sections_count, + $lt,$showcredits,$defaultcredits,$crstype) = @_; + my $creditem; + my $row = &Apache::loncommon::start_data_table_row(). + ' '."\n". + ' '.$plrole.''."\n". + ' '.$area.'
    Domain: '.$domain.''."\n"; + if (($showcredits) && ($role eq 'st') && ($crstype eq 'Course')) { + $row .= + ''; + } else { + $row .= ' '; + } + 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"; + } + } + $row .= < +$lt->{'ssd'} + +$lt->{'sed'} +ENDTIMEENTRY + $row .= &Apache::loncommon::end_data_table_row(); + return $row; +} + +sub course_level_dc { + my ($dcdom,$showcredits) = @_; + 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,'Select','crstype'); + my $credit_elem; + if ($showcredits) { + $credit_elem = 'credits'; + } + my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($dcdom,'currsec','cu','role','Course/Community Browser',$credit_elem); + my %lt=&Apache::lonlocal::texthash( + 'rol' => "Role", + 'grs' => "Section", + 'exs' => "Existing sections", + 'new' => "Define new section", + 'sta' => "Start", + 'end' => "End", + 'ssd' => "Set Start Date", + 'sed' => "Set End Date", + 'scc' => "Course/Community", + 'crd' => "Credits", + ); + my $header = '

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

    '. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ''.$lt{'scc'}.''.$lt{'rol'}.''."\n". + ''.$lt{'grs'}.''."\n"; + $header .= ''.$lt{'crd'}.''."\n" if ($showcredits); + $header .= ''.$lt{'sta'}.''.$lt{'end'}.''."\n". + &Apache::loncommon::end_data_table_header_row(); + my $otheritems = &Apache::loncommon::start_data_table_row()."\n". + '
    '. + $courseform.(' ' x4).''."\n". + '
    '. + ''. + ''. + ''. + ''. + '
    '.$lt{'exs'}.'
       '.$lt{'new'}.'
    '. + ''. + ''. + ''. + '
    '."\n"; + if ($showcredits) { + $otheritems .= '
    '."\n". + ''."\n"; + } + $otheritems .= <
    +$lt{'ssd'} +
    +$lt{'sed'} +ENDTIMEENTRY + $otheritems .= &Apache::loncommon::end_data_table_row(). + &Apache::loncommon::end_data_table()."\n"; + return $cb_jscript.$header.$hiddenitems.$otheritems; +} + +sub update_selfenroll_config { + my ($r,$cid,$cdom,$cnum,$context,$crstype,$currsettings) = @_; + return unless (ref($currsettings) eq 'HASH'); + my ($row,$lt) = &Apache::lonuserutils::get_selfenroll_titles(); + my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum); + my (%changes,%warning); + my $curr_types; + my %noedit; + unless ($context eq 'domain') { + %noedit = &get_noedit_fields($cdom,$cnum,$crstype,$row); + } + if (ref($row) eq 'ARRAY') { + foreach my $item (@{$row}) { + next if ($noedit{$item}); + if ($item eq 'enroll_dates') { + my (%currenrolldate,%newenrolldate); + foreach my $type ('start','end') { + $currenrolldate{$type} = $currsettings->{'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} = $currsettings->{'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 = $currsettings->{'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 = $currsettings->{'selfenroll_limit'}; + $currlimit = 'none' if ($currlimit eq ''); + my $currcap = $currsettings->{'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 = $currsettings->{'selfenroll_approval'}; + my $currnotifylist = $currsettings->{'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 = $currsettings->{'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{$cid}) eq 'HASH') { + foreach my $item ('selfenroll_types','selfenroll_start_date','selfenroll_end_date') { + if (exists($changes{'internal.'.$item})) { + $crsinfo{$cid}{$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 = $currsettings->{'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 = $currsettings->{'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 %selfdescs = &Apache::lonuserutils::selfenroll_default_descs(); + my ($newval,$newnotify); + if (exists($changes{'internal.selfenroll_notifylist'})) { + $newnotify = $changes{'internal.selfenroll_notifylist'}; + } else { + $newnotify = $currsettings->{'selfenroll_notifylist'}; + } + if (exists($changes{'internal.selfenroll_approval'})) { + if ($changes{'internal.selfenroll_approval'} !~ /^[012]$/) { + $changes{'internal.selfenroll_approval'} = '0'; + } + $newval = $selfdescs{'approval'}{$changes{'internal.selfenroll_approval'}}; + } else { + my $currapproval = $currsettings->{'selfenroll_approval'}; + if ($currapproval !~ /^[012]$/) { + $currapproval = 0; + } + $newval = $selfdescs{'approval'}{$currapproval}; + } + $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('
    '); + if ($env{'course.'.$cid.'.description'} ne '') { + my %newenvhash; + foreach my $key (keys(%changes)) { + $newenvhash{'course.'.$cid.'.'.$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 $visactions = &cat_visibility(); + my ($cathash,%cattype); + my %domconfig = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom); + if (ref($domconfig{'coursecategories'}) eq 'HASH') { + $cathash = $domconfig{'coursecategories'}{'cats'}; + $cattype{'auth'} = $domconfig{'coursecategories'}{'auth'}; + $cattype{'unauth'} = $domconfig{'coursecategories'}{'unauth'}; + } else { + $cathash = {}; + $cattype{'auth'} = 'std'; + $cattype{'unauth'} = 'std'; + } + if (($cattype{'auth'} eq 'none') && ($cattype{'unauth'} eq 'none')) { + $r->print('
    '.$visactions->{'miss'}.'
    '.$visactions->{'yous'}. + '
    '. + '
    '.$visactions->{'take'}.'
      '. + '
    • '.$visactions->{'dc_chgconf'}.'
    • '. + '
    '); + } elsif (($cattype{'auth'} !~ /^(std|domonly)$/) && ($cattype{'unauth'} !~ /^(std|domonly)$/)) { + if ($currsettings->{'uniquecode'}) { + $r->print(''.$visactions->{'vis'}.''); + } else { + $r->print('
    '.$visactions->{'miss'}.'
    '.$visactions->{'yous'}. + '
    '. + '
    '.$visactions->{'take'}.'
      '. + '
    • '.$visactions->{'dc_setcode'}.'
    • '. + '

    '); + } + } else { + my ($visible,$cansetvis,$vismsgs) = &visible_in_stdcat($cdom,$cnum,\%domconfig); + 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; +} + #---------------------------------------------- end functions for &phase_two #--------------------------------- functions for &phase_two and &phase_three