--- loncom/interface/lonuserutils.pm 2016/07/24 14:34:59 1.174 +++ loncom/interface/lonuserutils.pm 2016/11/09 00:32:45 1.178 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.174 2016/07/24 14:34:59 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.178 2016/11/09 00:32:45 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -30,6 +30,22 @@ package Apache::lonuserutils; +=pod + +=head1 NAME + +Apache::lonuserutils.pm + +=head1 SYNOPSIS + + Utilities for management of users and custom roles + + Provides subroutines called by loncreateuser.pm + +=head1 OVERVIEW + +=cut + use strict; use Apache::lonnet; use Apache::loncommon(); @@ -1531,10 +1547,10 @@ sub curr_role_permissions { # ======================================================= Existing Custom Roles sub my_custom_roles { - my ($crstype) = @_; + my ($crstype,$udom,$uname) = @_; my %returnhash=(); my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1}); - my %rolehash=&Apache::lonnet::dump('roles'); + my %rolehash=&Apache::lonnet::dump('roles',$udom,$uname); foreach my $key (keys(%rolehash)) { if ($key=~/^rolesdef\_(\w+)$/) { if ($crstype eq 'Community') { @@ -2547,9 +2563,13 @@ $verify_action_js function username_display_launch(username,domain) { var target; - for (var i=0; i<document.$formname.usernamelink.length; i++) { - if (document.$formname.usernamelink[i].checked) { - target = document.$formname.usernamelink[i].value; + if (!document.$formname.usernamelink.length) { + target = document.$formname.usernamelink.value; + } else { + for (var i=0; i<document.$formname.usernamelink.length; i++) { + if (document.$formname.usernamelink[i].checked) { + target = document.$formname.usernamelink[i].value; + } } } if (target == 'modify') { @@ -2973,6 +2993,12 @@ END } (keys(%$userlist)); } my $rowcount = 0; + my $disabled; + if ($mode eq 'autoenroll') { + unless ($permission->{'cusr'}) { + $disabled = ' disabled="disabled"'; + } + } foreach my $user (@sorted_users) { my %in; my $sdata = $userlist->{$user}; @@ -3009,16 +3035,16 @@ END if ($mode eq 'autoenroll') { my $cellentry; if ($in{'type'} eq 'auto') { - $cellentry = '<b>'.&mt('auto').'</b> <label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Change').'</label>'; + $cellentry = '<b>'.&mt('auto').'</b> <label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Change').'</label>'; $autocount ++; } else { - $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><span class="LC_nobreak"><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Change').'</label></span></td></tr><tr><td><span class="LC_nobreak">'; + $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><span class="LC_nobreak"><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Change').'</label></span></td></tr><tr><td><span class="LC_nobreak">'; $manualcount ++; if ($in{'lockedtype'}) { - $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Unlock').'</label>'; + $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Unlock').'</label>'; $unlockcount ++; } else { - $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Lock').'</label>'; + $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Lock').'</label>'; $lockcount ++; } $cellentry .= '</span></td></tr></table>'; @@ -5396,13 +5422,13 @@ sub set_login { } sub course_sections { - my ($sections_count,$role,$current_sec) = @_; + my ($sections_count,$role,$current_sec,$disabled) = @_; my $output = ''; my @sections = (sort {$a <=> $b} keys(%{$sections_count})); my $numsec = scalar(@sections); my $is_selected = ' selected="selected"'; if ($numsec <= 1) { - $output = '<select name="currsec_'.$role.'" >'."\n". + $output = '<select name="currsec_'.$role.'"'.$disabled.'>'."\n". ' <option value="">'.&mt('Select').'</option>'."\n"; if ($current_sec eq 'none') { $output .= @@ -5425,7 +5451,7 @@ sub course_sections { my $multiple = 4; if (scalar(@sections) < 4) { $multiple = scalar(@sections); } if ($role eq 'st') { - $output .= '>'."\n". + $output .= $disabled.'>'."\n". ' <option value="">'.&mt('Select').'</option>'."\n"; if ($current_sec eq 'none') { $output .= @@ -5435,7 +5461,7 @@ sub course_sections { ' <option value="">'.&mt('No section')."</option>\n"; } } else { - $output .= 'multiple="multiple" size="'.$multiple.'">'."\n"; + $output .= 'multiple="multiple" size="'.$multiple.'"'.$disabled.'>'."\n"; } foreach my $sec (@sections) { if ($current_sec eq $sec) { @@ -5652,6 +5678,9 @@ sub can_create_user { my $cancreate = 1; if (&Apache::lonnet::allowed('mau',$dom)) { return $cancreate; + } elsif ($context eq 'domain') { + $cancreate = 0; + return $cancreate; } if (ref($domconf{'usercreation'}) eq 'HASH') { if (ref($domconf{'usercreation'}{'cancreate'}) eq 'HASH') { @@ -5794,7 +5823,7 @@ sub roles_by_context { } elsif ($context eq 'author') { @allroles = ('ca','aa'); } elsif ($context eq 'domain') { - @allroles = ('li','ad','dg','sc','au','dc'); + @allroles = ('li','ad','dg','dh','sc','au','dc'); } return @allroles; } @@ -5871,7 +5900,12 @@ sub get_permission { if (&Apache::lonnet::allowed('ccr',$env{'request.role.domain'})) { $permission{'custom'} = 1; } - $permission{'view'} = $permission{'cusr'}; + if (&Apache::lonnet::allowed('vac',$env{'request.role.domain'})) { + $permission{'activity'} = 1; + } + if (&Apache::lonnet::allowed('vur',$env{'request.role.domain'})) { + $permission{'view'} = 1; + } } my $allowed = 0; foreach my $perm (values(%permission)) { @@ -6307,5 +6341,336 @@ sub selfenrollment_administration { return (\@in_course,\@in_domain); } +sub custom_role_header { + my ($context,$crstype,$templaterolerefs,$prefix) = @_; + my %lt = &Apache::lonlocal::texthash( + sele => 'Select a Template', + ); + my ($context_code,$button_code); + if ($context eq 'domain') { + $context_code = &custom_coursetype_switch($crstype,$prefix); + } + if (ref($templaterolerefs) eq 'ARRAY') { + foreach my $role (@{$templaterolerefs}) { + my $display = 'inline'; + if (($context eq 'domain') && ($role eq 'co')) { + $display = 'none'; + } + $button_code .= &make_button_code($role,$crstype,$display,$prefix).' '; + } + } + return <<"END"; +<div class="LC_left_float"> +<fieldset> +<legend>$lt{'sele'}</legend> +$button_code +</fieldset></div> +$context_code +<br clear="all" /> +END +} + +sub custom_coursetype_switch { + my ($crstype,$prefix) = @_; + my ($checkedcourse,$checkedcommunity); + if ($crstype eq 'Community') { + $checkedcommunity = ' checked="checked"'; + } else { + $checkedcourse = ' checked="checked"'; + } + my %lt = &Apache::lonlocal::texthash( + cont => 'Context', + cour => 'Course', + comm => 'Community', + ); + return <<"END"; +<div class="LC_left_float"> +<fieldset> +<legend>$lt{'cont'}</legend> +<label> +<input type="radio" name="${prefix}_custrolecrstype" value="Course"$checkedcourse onclick="javascript:customSwitchType('$prefix');" /> +$lt{'cour'} +</label> +<label> +<input type="radio" name="${prefix}_custrolecrstype" value="Community"$checkedcommunity onclick="javascript:customSwitchType('$prefix');" /> +$lt{'comm'} +</label> +</fieldset> +</div> +END +} + +sub custom_role_table { + my ($crstype,$full,$levels,$levelscurrent,$prefix) = @_; + return unless ((ref($full) eq 'HASH') && (ref($levels) eq 'HASH') && + (ref($levelscurrent) eq 'HASH')); + my %lt=&Apache::lonlocal::texthash ( + 'prv' => "Privilege", + 'crl' => "Course Level", + 'dml' => "Domain Level", + 'ssl' => "System Level"); + my %cr = ( + course => '_c', + domain => '_d', + system => '_s', + ); + + my $output=&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th>'.$lt{'prv'}.'</th><th>'.$lt{'crl'}.'</th><th>'.$lt{'dml'}. + '</th><th>'.$lt{'ssl'}.'</th>'. + &Apache::loncommon::end_data_table_header_row(); + foreach my $priv (sort(keys(%{$full}))) { + my $privtext = &Apache::lonnet::plaintext($priv,$crstype); + $output .= &Apache::loncommon::start_data_table_row(). + '<td><span id="'.$prefix.$priv.'">'.$privtext.'</span></td>'; + foreach my $type ('course','domain','system') { + if (($type eq 'system') && ($priv eq 'bre') && ($crstype eq 'Community')) { + $output .= '<td> </td>'; + } else { + $output .= '<td>'. + ($levels->{$type}{$priv}?'<input type="checkbox" id="'.$prefix.$priv.$cr{$type}.'"'. + ' name="'.$prefix.$priv.$cr{$type}.'"'. + ($levelscurrent->{$type}{$priv}?' checked="checked"':'').' />':' '). + '</td>'; + } + } + $output .= &Apache::loncommon::end_data_table_row(); + } + $output .= &Apache::loncommon::end_data_table(); + return $output; +} + +sub custom_role_privs { + my ($privs,$full,$levels,$levelscurrent)= @_; + return unless ((ref($privs) eq 'HASH') && (ref($full) eq 'HASH') && + (ref($levels) eq 'HASH') && (ref($levelscurrent) eq 'HASH')); + my %cr = ( + course => 'cr:c', + domain => 'cr:d', + system => 'cr:s', + ); + foreach my $type ('course','domain','system') { + foreach my $item (split(/\:/,$Apache::lonnet::pr{$cr{$type}})) { + my ($priv,$restrict)=split(/\&/,$item); + if (!$restrict) { $restrict='F'; } + $levels->{$type}->{$priv}=$restrict; + if ($privs->{$type}=~/\:$priv/) { + $levelscurrent->{$type}->{$priv}=1; + } + $full->{$priv}=1; + } + } + return; +} + +sub custom_template_roles { + my ($context,$crstype) = @_; + my @template_roles = ("in","ta","ep"); + if (($context eq 'domain') || ($context eq 'domprefs')) { + push(@template_roles,"ad"); + } + push(@template_roles,"st"); + if ($context eq 'domain') { + unshift(@template_roles,('co','cc')); + } else { + if ($crstype eq 'Community') { + unshift(@template_roles,'co'); + } else { + unshift(@template_roles,'cc'); + } + } + return @template_roles; +} + +sub custom_roledefs_js { + my ($context,$crstype,$formname,$full,$templaterolesref,$jsback) = @_; + my $button_code = "\n"; + my $head_script = "\n"; + my (%roletitlestr,$rolenamestr); + my %role_titles = ( + Course => [], + Community => [], + ); + $head_script .= '<script type="text/javascript">'."\n" + .'// <![CDATA['."\n"; + if (ref($templaterolesref) eq 'ARRAY') { + if ($context eq 'domain') { + $rolenamestr = join("','",@{$templaterolesref}); + } + foreach my $role (@{$templaterolesref}) { + $head_script .= &make_script_template($role,$crstype,$formname); + if ($context eq 'domain') { + foreach my $type ('Course','Community') { + push(@{$role_titles{$type}},&Apache::lonnet::plaintext($role,$type)); + } + } + } + } + if ($context eq 'domain') { + foreach my $type ('Course','Community') { + $roletitlestr{$type} = join("','",@{$role_titles{$type}}); + } + my %pt = ( + Community => { + cst => &mt('Grant/revoke role of Member'), + mdc => &mt('Edit community contents'), + pch => &mt('Post discussion on community resources'), + pfo => &mt('Print for other users and entire community'), + }, + Course => { + cst => &mt('Grant/revoke role of Student'), + mdc => &mt('Edit course contents'), + pch => &mt('Post discussion on course resources'), + pfo => &mt('Print for other users and entire course'), + }, + ); + $head_script .= <<"ENDJS"; +function customSwitchType(prefix) { + var privnames = new Array('cst','mdc','pch','pfo'); + var privtxtcrs = new Array('$pt{Course}{cst}','$pt{Course}{mdc}','$pt{Course}{pch}','$pt{Course}{pfo}'); + var privtxtcom = new Array('$pt{Community}{cst}','$pt{Community}{mdc}','$pt{Community}{pch}','$pt{Community}{pfo}'); + var rolenames = new Array('$rolenamestr'); + var rolescrs = new Array('$roletitlestr{Course}'); + var rolescom = new Array('$roletitlestr{Community}'); + var radio = prefix+'_custrolecrstype'; + if (document.$formname.elements[radio].length > 1) { + for (var i=0; i<document.$formname.elements[radio].length; i++) { + if (document.$formname.elements[radio][i].checked) { + if ((document.getElementById(prefix+'bre_s')) && (document.getElementById(prefix+'bro_s'))) { + if (document.$formname.elements[radio][i].value == 'Community') { + if (document.getElementById(prefix+'bre_s').checked) { + document.getElementById(prefix+'bro_s').checked = true; + document.getElementById(prefix+'bre_s').checked = false; + + } + document.getElementById(prefix+'bre_s').style.visibility = 'hidden'; + } else { + document.getElementById(prefix+'bre_s').style.visibility = 'visible'; + if (document.getElementById(prefix+'bro_s').checked) { + document.getElementById(prefix+'bre_s').checked = true; + document.getElementById(prefix+'bro_s').checked = false; + } + } + } + for (var j=0; j<privnames.length; j++) { + if (document.getElementById(prefix+privnames[j])) { + if (document.getElementById(prefix+privnames[j])) { + if (document.$formname.elements[radio][i].value == 'Course') { + document.getElementById(prefix+privnames[j]).innerHTML = privtxtcrs[j]; + } else { + document.getElementById(prefix+privnames[j]).innerHTML = privtxtcom[j]; + } + } + } + } + for (var j=0; j<rolenames.length; j++) { + if (document.getElementById(prefix+rolenames[j])) { + if (document.getElementById(prefix+rolenames[j])) { + if (document.$formname.elements[radio][i].value == 'Course') { + document.getElementById(prefix+rolenames[j]).value = rolescrs[j]; + if (rolenames[j] == 'cc') { + document.getElementById(prefix+rolenames[j]).style.display = 'inline'; + } + if (rolenames[j] == 'co') { + document.getElementById(prefix+rolenames[j]).style.display = 'none'; + } + } else { + document.getElementById(prefix+rolenames[j]).value = rolescom[j]; + if (rolenames[j] == 'cc') { + document.getElementById(prefix+rolenames[j]).style.display = 'none'; + } + if (rolenames[j] == 'co') { + document.getElementById(prefix+rolenames[j]).style.display = 'inline'; + } + } + } + } + } + } + } + } + return; +} +ENDJS + } + $head_script .= "\n".$jsback."\n" + .'// ]]>'."\n" + .'</script>'."\n"; + return $head_script; +} + +# -------------------------------------------------------- +sub make_script_template { + my ($role,$crstype,$formname) = @_; + my $return_script = 'function set_'.$role.'(prefix) {'."\n"; + my (%full_by_level,%role_priv); + foreach my $level ('c','d','s') { + foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) { + next if (($level eq 's') && ($crstype eq 'Community') && ($item eq 'bre&S')); + my ($priv,$restrict)=split(/\&/,$item); + $full_by_level{$level}{$priv}=1; + } + $role_priv{$level} = {}; + my @temp = split(/:/,$Apache::lonnet::pr{$role.':'.$level}); + foreach my $priv (@temp) { + my ($priv_item, $dummy) = split(/\&/,$priv); + $role_priv{$level}{$priv_item} = 1; + } + } + my %to_check = ( + c => ['c','d','s'], + d => ['d','s'], + s => ['s'], + ); + foreach my $level ('c','d','s') { + if (ref($full_by_level{$level}) eq 'HASH') { + foreach my $priv (keys(%{$full_by_level{$level}})) { + my $value = 'false'; + if (ref($to_check{$level}) eq 'ARRAY') { + foreach my $lett (@{$to_check{$level}}) { + if (exists($role_priv{$lett}{$priv})) { + $value = 'true'; + last; + } + } + $return_script .= "document.$formname.elements[prefix+'".$priv."_".$level."'].checked = $value;\n"; + } + } + } + } + $return_script .= '}'."\n"; + return ($return_script); +} +# ---------------------------------------------------------- +sub make_button_code { + my ($role,$crstype,$display,$prefix) = @_; + my $label = &Apache::lonnet::plaintext($role,$crstype); + my $button_code = '<input type="button" onclick="set_'.$role."('$prefix'".')" '. + 'id="'.$prefix.$role.'" value="'.$label.'" '. + 'style="display:'.$display.'" />'; + return ($button_code); +} + +sub custom_role_update { + my ($rolename,$prefix) = @_; +# ------------------------------------------------------- What can be assigned? + my %privs = ( + c => '', + d => '', + s => '', + ); + foreach my $level (keys(%privs)) { + foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) { + my ($priv,$restrict)=split(/\&/,$item); + if (!$restrict) { $restrict=''; } + if ($env{'form.'.$prefix.$priv.'_'.$level}) { + $privs{$level} .=':'.$item; + } + } + } + return %privs; +} + 1;