--- loncom/interface/domainprefs.pm 2024/08/18 01:12:54 1.160.6.118.2.23
+++ loncom/interface/domainprefs.pm 2022/08/24 20:58:50 1.412
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.160.6.118.2.23 2024/08/18 01:12:54 raeburn Exp $
+# $Id: domainprefs.pm,v 1.412 2022/08/24 20:58:50 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -95,7 +95,8 @@ about default quota sizes for portfolio
institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.),
but is now also used to manage availability of user tools:
i.e., blogs, aboutme page, and portfolios, and the course request tool,
-used by course owners to request creation of a course.
+used by course owners to request creation of a course, and to display/store
+default quota sizes for Authoring Spaces.
Outputs: 1
@@ -103,8 +104,8 @@ $datatable - HTML containing form eleme
In the case of course requests, radio buttons are displayed for each institutional
affiliate type (and also default, and _LC_adv) for each of the course types
-(official, unofficial, community, textbook, and lti).
-In each case the radio buttons allow the selection of one of four values:
+(official, unofficial, community, textbook, placement, and lti).
+In each case the radio buttons allow the selection of one of four values:
0, approval, validate, autolimit=N (where N is blank, or a positive integer).
which have the following effects:
@@ -166,17 +167,16 @@ use Apache::lonmsg();
use Apache::lonconfigsettings;
use Apache::lonuserutils();
use Apache::loncoursequeueadmin();
-use Apache::courseprefs();
use LONCAPA qw(:DEFAULT :match);
use LONCAPA::Enrollment;
use LONCAPA::lonauthcgi();
+use LONCAPA::SSL;
use File::Copy;
use Locale::Language;
use DateTime::TimeZone;
use DateTime::Locale;
use Time::HiRes qw( sleep );
use Net::CIDR;
-use Crypt::CBC;
my $registered_cleanup;
my $modified_urls;
@@ -220,27 +220,17 @@ sub handler {
'serverstatuses','requestcourses','helpsettings',
'coursedefaults','usersessions','loadbalancing',
'requestauthor','selfenrollment','inststatus',
- 'passwords','ltitools','toolsec','lti','ltisec',
- 'wafproxy','ipaccess','authordefaults'],$dom);
+ 'ltitools','ssl','trust','lti','ltisec','privacy','passwords',
+ 'proctoring','wafproxy','ipaccess'],$dom);
my %encconfig =
- &Apache::lonnet::get_dom('encconfig',['ltitools','lti','linkprot'],$dom,undef,1);
- my ($checked_is_home,$is_home);
+ &Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring','linkprot'],$dom,undef,1);
if (ref($domconfig{'ltitools'}) eq 'HASH') {
if (ref($encconfig{'ltitools'}) eq 'HASH') {
- my $home = &Apache::lonnet::domain($dom,'primary');
- unless (($home eq 'no_host') || ($home eq '')) {
- my @ids=&Apache::lonnet::current_machine_ids();
- if (grep(/^\Q$home\E$/,@ids)) {
- $is_home = 1;
- }
- }
- $checked_is_home = 1;
foreach my $id (keys(%{$domconfig{'ltitools'}})) {
if ((ref($domconfig{'ltitools'}{$id}) eq 'HASH') &&
(ref($encconfig{'ltitools'}{$id}) eq 'HASH')) {
- $domconfig{'ltitools'}{$id}{'key'} = $encconfig{'ltitools'}{$id}{'key'};
- if (($is_home) && ($phase eq 'process')) {
- $domconfig{'ltitools'}{$id}{'secret'} = $encconfig{'ltitools'}{$id}{'secret'};
+ foreach my $item ('key','secret') {
+ $domconfig{'ltitools'}{$id}{$item} = $encconfig{'ltitools'}{$id}{$item};
}
}
}
@@ -248,22 +238,11 @@ sub handler {
}
if (ref($domconfig{'lti'}) eq 'HASH') {
if (ref($encconfig{'lti'}) eq 'HASH') {
- unless ($checked_is_home) {
- my $home = &Apache::lonnet::domain($dom,'primary');
- unless (($home eq 'no_host') || ($home eq '')) {
- my @ids=&Apache::lonnet::current_machine_ids();
- if (grep(/^\Q$home\E$/,@ids)) {
- $is_home = 1;
- }
- }
- $checked_is_home = 1;
- }
foreach my $id (keys(%{$domconfig{'lti'}})) {
if ((ref($domconfig{'lti'}{$id}) eq 'HASH') &&
(ref($encconfig{'lti'}{$id}) eq 'HASH')) {
- $domconfig{'lti'}{$id}{'key'} = $encconfig{'lti'}{$id}{'key'};
- if (($is_home) && ($phase eq 'process')) {
- $domconfig{'lti'}{$id}{'secret'} = $encconfig{'lti'}{$id}{'secret'};
+ foreach my $item ('key','secret') {
+ $domconfig{'lti'}{$id}{$item} = $encconfig{'lti'}{$id}{$item};
}
}
}
@@ -286,12 +265,25 @@ sub handler {
}
}
}
+ if (ref($domconfig{'proctoring'}) eq 'HASH') {
+ if (ref($encconfig{'proctoring'}) eq 'HASH') {
+ foreach my $provider (keys(%{$domconfig{'proctoring'}})) {
+ if ((ref($domconfig{'proctoring'}{$provider}) eq 'HASH') &&
+ (ref($encconfig{'proctoring'}{$provider}) eq 'HASH')) {
+ foreach my $item ('key','secret') {
+ $domconfig{'proctoring'}{$provider}{$item} = $encconfig{'proctoring'}{$provider}{$item};
+ }
+ }
+ }
+ }
+ }
my @prefs_order = ('rolecolors','login','ipaccess','defaults','wafproxy','passwords',
'quotas','autoenroll','autoupdate','autocreate','directorysrch',
- 'contacts','usercreation','selfcreation','usermodification',
- 'scantron','requestcourses','requestauthor','coursecategories',
- 'serverstatuses','helpsettings','coursedefaults',
- 'authordefaults','ltitools','selfenrollment','usersessions','lti');
+ 'contacts','privacy','usercreation','selfcreation',
+ 'usermodification','scantron','requestcourses','requestauthor',
+ 'coursecategories','serverstatuses','helpsettings','coursedefaults',
+ 'ltitools','proctoring','selfenrollment','usersessions','ssl',
+ 'trust','lti');
my %existing;
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
@@ -367,11 +359,11 @@ sub handler {
modify => \&modify_passwords,
},
'quotas' =>
- { text => 'Blogs, personal pages/timezones, portfolio/quotas',
+ { text => 'Blogs, personal web pages, webDAV/quotas, portfolios',
help => 'Domain_Configuration_Quotas',
header => [{col1 => 'User affiliation',
col2 => 'Available tools',
- col3 => 'Portfolio quota (MB)',}],
+ col3 => 'Quotas, MB; (Authoring requires role)',}],
print => \&print_quotas,
modify => \&modify_quotas,
},
@@ -552,6 +544,20 @@ sub handler {
print => \&print_selfenrollment,
modify => \&modify_selfenrollment,
},
+ 'privacy' =>
+ {text => 'Availability of User Information',
+ help => 'Domain_Configuration_User_Privacy',
+ header => [{col1 => 'Role assigned in different domain',
+ col2 => 'Approval options'},
+ {col1 => 'Role assigned in different domain to user of type',
+ col2 => 'User information available in that domain'},
+ {col1 => "Role assigned in user's domain",
+ col2 => 'Information viewable by privileged user'},
+ {col1 => "Role assigned in user's domain",
+ col2 => 'Information viewable by unprivileged user'}],
+ print => \&print_privacy,
+ modify => \&modify_privacy,
+ },
'usersessions' =>
{text => 'User session hosting/offloading',
help => 'Domain_Configuration_User_Sessions',
@@ -575,27 +581,67 @@ sub handler {
print => \&print_loadbalancing,
modify => \&modify_loadbalancing,
},
- 'ltitools' =>
+ 'ltitools' =>
{text => 'External Tools (LTI)',
help => 'Domain_Configuration_LTI_Tools',
- header => [{col1 => 'Encryption of shared secrets',
- col2 => 'Settings'},
- {col1 => 'Rules for shared secrets',
- col2 => 'Settings'},
- {col1 => 'Providers',
- col2 => 'Settings',}],
+ header => [{col1 => 'Setting',
+ col2 => 'Value',}],
print => \&print_ltitools,
modify => \&modify_ltitools,
},
- 'lti' =>
+ 'proctoring' =>
+ {text => 'Remote Proctoring Integration',
+ help => 'Domain_Configuration_Proctoring',
+ header => [{col1 => 'Name',
+ col2 => 'Configuration'}],
+ print => \&print_proctoring,
+ modify => \&modify_proctoring,
+ },
+ 'ssl' =>
+ {text => 'LON-CAPA Network (SSL)',
+ help => 'Domain_Configuration_Network_SSL',
+ header => [{col1 => 'Server',
+ col2 => 'Certificate Status'},
+ {col1 => 'Connections to other servers',
+ col2 => 'Rules'},
+ {col1 => 'Connections from other servers',
+ col2 => 'Rules'},
+ {col1 => "Replicating domain's published content",
+ col2 => 'Rules'}],
+ print => \&print_ssl,
+ modify => \&modify_ssl,
+ },
+ 'trust' =>
+ {text => 'Trust Settings',
+ help => 'Domain_Configuration_Trust',
+ header => [{col1 => "Access to this domain's content by others",
+ col2 => 'Rules'},
+ {col1 => "Access to other domain's content by this domain",
+ col2 => 'Rules'},
+ {col1 => "Enrollment in this domain's courses by others",
+ col2 => 'Rules',},
+ {col1 => "Co-author roles in this domain for others",
+ col2 => 'Rules',},
+ {col1 => "Co-author roles for this domain's users elsewhere",
+ col2 => 'Rules',},
+ {col1 => "Domain roles in this domain assignable to others",
+ col2 => 'Rules'},
+ {col1 => "Course catalog for this domain displayed elsewhere",
+ col2 => 'Rules'},
+ {col1 => "Requests for creation of courses in this domain by others",
+ col2 => 'Rules'},
+ {col1 => "Users in other domains can send messages to this domain",
+ col2 => 'Rules'},],
+ print => \&print_trust,
+ modify => \&modify_trust,
+ },
+ 'lti' =>
{text => 'LTI Link Protection and LTI Consumers',
help => 'Domain_Configuration_LTI_Provider',
header => [{col1 => 'Encryption of shared secrets',
col2 => 'Settings'},
- {col1 => 'Rules for shared secrets',
+ {col1 => 'Rules for shared secrets',
col2 => 'Settings'},
- {col1 => 'Link Protectors in Courses',
- col2 => 'Values'},
{col1 => 'Link Protectors',
col2 => 'Settings'},
{col1 => 'Consumers',
@@ -603,7 +649,7 @@ sub handler {
print => \&print_lti,
modify => \&modify_lti,
},
- 'ipaccess' =>
+ 'ipaccess' =>
{text => 'IP-based access control',
help => 'Domain_Configuration_IP_Access',
header => [{col1 => 'Setting',
@@ -611,16 +657,6 @@ sub handler {
print => \&print_ipaccess,
modify => \&modify_ipaccess,
},
- 'authordefaults' =>
- {text => 'Authoring Space defaults',
- help => 'Domain_Configuration_Author_Defaults',
- header => [{col1 => 'Defaults which can be overridden by Author',
- col2 => 'Settings',},
- {col1 => 'Defaults which can be overridden by a Dom. Coord.',
- col2 => 'Settings',},],
- print => \&print_authordefaults,
- modify => \&modify_authordefaults,
- },
);
if (keys(%servers) > 1) {
$prefs{'login'} = { text => 'Log-in page options',
@@ -810,16 +846,22 @@ sub process_changes {
$output = &modify_loadbalancing($dom,%domconfig);
} elsif ($action eq 'ltitools') {
$output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
+ } elsif ($action eq 'proctoring') {
+ $output = &modify_proctoring($r,$dom,$action,$lastactref,%domconfig);
+ } elsif ($action eq 'ssl') {
+ $output = &modify_ssl($dom,$lastactref,%domconfig);
+ } elsif ($action eq 'trust') {
+ $output = &modify_trust($dom,$lastactref,%domconfig);
} elsif ($action eq 'lti') {
$output = &modify_lti($r,$dom,$action,$lastactref,%domconfig);
+ } elsif ($action eq 'privacy') {
+ $output = &modify_privacy($dom,%domconfig);
} elsif ($action eq 'passwords') {
$output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);
} elsif ($action eq 'wafproxy') {
$output = &modify_wafproxy($dom,$action,$lastactref,%domconfig);
} elsif ($action eq 'ipaccess') {
$output = &modify_ipaccess($dom,$lastactref,%domconfig);
- } elsif ($action eq 'authordefaults') {
- $output = &modify_authordefaults($dom,$lastactref,%domconfig);
}
return $output;
}
@@ -848,13 +890,15 @@ sub print_config_box {
&Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
$output =
- &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,
+ &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,\%full,
\@templateroles);
} elsif ($action eq 'ltitools') {
- $output .= &Apache::lonconfigsettings::ltitools_javascript($settings);
+ $output .= <itools_javascript($settings);
} elsif ($action eq 'lti') {
- $output .= &passwords_javascript('ltisecrets')."\n".
+ $output .= &passwords_javascript('secrets')."\n".
<i_javascript($dom,$settings);
+ } elsif ($action eq 'proctoring') {
+ $output .= &proctoring_javascript($settings);
} elsif ($action eq 'wafproxy') {
$output .= &wafproxy_javascript($dom);
} elsif ($action eq 'autoupdate') {
@@ -865,8 +909,6 @@ sub print_config_box {
$output .= &saml_javascript();
} elsif ($action eq 'ipaccess') {
$output .= &ipaccess_javascript($settings);
- } elsif ($action eq 'authordefaults') {
- $output .= &authordefaults_javascript();
}
$output .=
'
+
+
+
+ '.&mt($item->{'header'}->[3]->{'col1'}).'
+ '.&mt($item->{'header'}->[3]->{'col2'}).' '.
+ $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
} elsif ($action eq 'login') {
if ($numheaders == 5) {
$output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal).'
@@ -1112,8 +1190,8 @@ sub print_config_box {
- '.&mt($item->{'header'}->[4]->{'col1'}).'
- '.&mt($item->{'header'}->[4]->{'col2'}).'
+ '.&mt($item->{'header'}->[4]->{'col1'}).'
+ '.&mt($item->{'header'}->[4]->{'col2'}).'
'.
&print_validation_rows('requestcourses',$dom,$settings,\$rowtotal);
} elsif ($action eq 'requestauthor') {
@@ -1128,9 +1206,9 @@ sub print_config_box {
- '.
+ '.
&mt($item->{'header'}->[2]->{'col1'}).'
- '.
+ '.
&mt($item->{'header'}->[2]->{'col2'}).'
'.
&print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
@@ -1158,30 +1236,30 @@ sub print_config_box {
'.&mt($item->{'header'}->[0]->{'col1'}).' ';
} elsif ($action eq 'serverstatuses') {
$output .= '
- '.&mt($item->{'header'}->[0]->{'col1'}).
+ '.&mt($item->{'header'}->[0]->{'col1'}).
' ('.&mt('Automatic access for Dom. Coords.').') ';
} else {
$output .= '
- '.&mt($item->{'header'}->[0]->{'col1'}).' ';
+ '.&mt($item->{'header'}->[0]->{'col1'}).' ';
}
if (defined($item->{'header'}->[0]->{'col3'})) {
- $output .= ''.
+ $output .= ' '.
&mt($item->{'header'}->[0]->{'col2'});
if ($action eq 'serverstatuses') {
$output .= ' ('.&mt('user1:domain1,user2:domain2 etc.').' )';
}
} else {
- $output .= ' '.
+ $output .= ' '.
&mt($item->{'header'}->[0]->{'col2'});
}
$output .= ' ';
if ($item->{'header'}->[0]->{'col3'}) {
if (defined($item->{'header'}->[0]->{'col4'})) {
- $output .= ''.
+ $output .= ' '.
&mt($item->{'header'}->[0]->{'col3'});
} else {
- $output .= ' '.
+ $output .= ' '.
&mt($item->{'header'}->[0]->{'col3'});
}
if ($action eq 'serverstatuses') {
@@ -1190,7 +1268,7 @@ sub print_config_box {
$output .= ' ';
}
if ($item->{'header'}->[0]->{'col4'}) {
- $output .= ''.
+ $output .= ' '.
&mt($item->{'header'}->[0]->{'col4'});
}
$output .= '';
@@ -1198,7 +1276,8 @@ sub print_config_box {
if ($action eq 'quotas') {
$output .= &print_quotas($dom,$settings,\$rowtotal,$action);
} elsif (($action eq 'autoenroll') || ($action eq 'autocreate') ||
- ($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||
+ ($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||
+ ($action eq 'ltitools') || ($action eq 'proctoring') ||
($action eq 'ipaccess')) {
$output .= $item->{'print'}->($dom,$settings,\$rowtotal);
}
@@ -1224,7 +1303,7 @@ sub print_login {
my $choice = $choices{'disallowlogin'};
$css_class = ' class="LC_odd_row"';
$datatable .= ' '.$choice.' '.
- ''.$choices{'hostid'}.' '.
+ ''.$choices{'hostid'}.' '.
''.$choices{'server'}.' '.
''.$choices{'serverpath'}.' '.
''.$choices{'custompath'}.' '.
@@ -1505,7 +1584,7 @@ sub print_login {
my $choice = $choices{'headtag'};
$css_class = ' class="LC_odd_row"';
$datatable .= ''.$choice.' '.
- ''.$choices{'hostid'}.' '.
+ ''.$choices{'hostid'}.' '.
''.$choices{'current'}.' '.
''.$choices{'action'}.' '.
''.$choices{'exempt'}.' '."\n";
@@ -2154,7 +2233,7 @@ sub display_color_options {
'';
foreach my $item (@{$bgs}) {
- $datatable .= ''.$choices->{$item};
+ $datatable .= ' '.$choices->{$item};
my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item};
if ($designs->{'bgs'}{$item}) {
$datatable .= ' ';
@@ -2182,7 +2261,7 @@ sub display_color_options {
'';
foreach my $item (@{$links}) {
my $color = $designs->{'links'}{$item} ? $designs->{'links'}{$item} : $defaults->{'links'}{$item};
- $datatable .= ''.$choices->{$item}."\n";
+ $datatable .= ' '.$choices->{$item}."\n";
if ($designs->{'links'}{$item}) {
$datatable.=' ';
}
@@ -2243,7 +2322,7 @@ sub login_text_colors {
my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_;
my $color_menu = '';
foreach my $item (@{$logintext}) {
- $color_menu .= ''.$choices->{$item};
+ $color_menu .= ' '.$choices->{$item};
my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item};
$color_menu .= ' ';
@@ -2276,7 +2355,7 @@ sub image_changes {
$role.'_del_'.$img.'" value="1" />'.&mt('Delete?').
' '.&mt('Replace:').' ';
} else {
- $output .= ''.$logincolors.&mt('Upload:').' ';
+ $output .= ' '.$logincolors.&mt('Upload:').' ';
}
}
return $output;
@@ -2290,12 +2369,12 @@ sub print_quotas {
} else {
$context = $action;
}
- my ($datatable,$defaultquota,@usertools,@options,%validations);
+ my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations);
my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
my $typecount = 0;
my ($css_class,%titles);
if ($context eq 'requestcourses') {
- @usertools = ('official','unofficial','community','textbook','lti');
+ @usertools = ('official','unofficial','community','textbook','placement','lti');
@options =('norequest','approval','validate','autolimit');
%validations = &Apache::lonnet::auto_courserequest_checks($dom);
%titles = &courserequest_titles();
@@ -2304,12 +2383,12 @@ sub print_quotas {
@options = ('norequest','approval','automatic');
%titles = &authorrequest_titles();
} else {
- @usertools = ('aboutme','blog','portfolio','portaccess','timezone');
+ @usertools = ('aboutme','blog','webdav','portfolio');
%titles = &tool_titles();
}
if (ref($types) eq 'ARRAY') {
foreach my $type (@{$types}) {
- my $currdefquota;
+ my ($currdefquota,$currauthorquota);
unless (($context eq 'requestcourses') ||
($context eq 'requestauthor')) {
if (ref($settings) eq 'HASH') {
@@ -2318,6 +2397,9 @@ sub print_quotas {
} else {
$currdefquota = $settings->{$type};
}
+ if (ref($settings->{authorquota}) eq 'HASH') {
+ $currauthorquota = $settings->{authorquota}->{$type};
+ }
}
}
if (defined($usertypes->{$type})) {
@@ -2405,12 +2487,9 @@ sub print_quotas {
}
} else {
my $checked = 'checked="checked" ';
- if ($item eq 'timezone') {
- $checked = '';
- }
if (ref($settings) eq 'HASH') {
if (ref($settings->{$item}) eq 'HASH') {
- if (!$settings->{$item}->{$type}) {
+ if ($settings->{$item}->{$type} == 0) {
$checked = '';
} elsif ($settings->{$item}->{$type} == 1) {
$checked = 'checked="checked" ';
@@ -2435,9 +2514,13 @@ sub print_quotas {
($context eq 'requestauthor')) {
$datatable .=
' '.
- ''.
+ ''.&mt('Portfolio').': '.
' '.(' ' x 2).
+ ''.&mt('Authoring').': '.
+ ' ';
}
$datatable .= ' ';
@@ -2446,12 +2529,16 @@ sub print_quotas {
}
unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
$defaultquota = '20';
+ $authorquota = '500';
if (ref($settings) eq 'HASH') {
if (ref($settings->{'defaultquota'}) eq 'HASH') {
$defaultquota = $settings->{'defaultquota'}->{'default'};
} elsif (defined($settings->{'default'})) {
$defaultquota = $settings->{'default'};
}
+ if (ref($settings->{'authorquota'}) eq 'HASH') {
+ $authorquota = $settings->{'authorquota'}->{'default'};
+ }
}
}
$typecount ++;
@@ -2563,9 +2650,12 @@ sub print_quotas {
$datatable .= '';
unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) {
$datatable .= ''.
- ''.
+ ''.&mt('Portfolio').': '.
' ';
+ $defaultquota.'" size="5" />'.(' ' x2).
+ ''.&mt('Authoring').': '.
+ ' ';
}
$datatable .= '';
$typecount ++;
@@ -2748,7 +2838,7 @@ sub print_studentcode {
my ($settings,$rowtotal) = @_;
my $rownum = 0;
my ($output,%current);
- my @crstypes = ('official','unofficial','community','textbook','lti');
+ my @crstypes = ('official','unofficial','community','textbook','placement','lti');
if (ref($settings) eq 'HASH') {
if (ref($settings->{'uniquecode'}) eq 'HASH') {
foreach my $type (@crstypes) {
@@ -3239,20 +3329,107 @@ function toggleWAF() {
ENDSCRIPT
}
-sub lti_javascript {
- my ($dom,$settings) = @_;
- my $togglejs = <i_toggle_js($dom);
- my $linkprot_js = &Apache::courseprefs::linkprot_javascript();
- unless (ref($settings) eq 'HASH') {
- return $togglejs.'
+sub proctoring_javascript {
+ my ($settings) = @_;
+ my (%ordered,$total,%jstext);
+ $total = 0;
+ if (ref($settings) eq 'HASH') {
+ foreach my $item (keys(%{$settings})) {
+ if (ref($settings->{$item}) eq 'HASH') {
+ my $num = $settings->{$item}{'order'};
+ $ordered{$num} = $item;
+ }
+ }
+ $total = scalar(keys(%{$settings}));
+ } else {
+ %ordered = (
+ 0 => 'proctorio',
+ 1 => 'examity',
+ );
+ $total = 2;
+ }
+ my @jsarray = ();
+ foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
+ push(@jsarray,$ordered{$item});
+ }
+ my $jstext = ' var proctors = Array('."'".join("','",@jsarray)."'".');'."\n";
+ return <<"ENDSCRIPT";
-';
+
+ENDSCRIPT
+}
+
+
+sub lti_javascript {
+ my ($dom,$settings) = @_;
+ my $togglejs = <i_toggle_js($dom);
+ unless (ref($settings) eq 'HASH') {
+ return $togglejs;
}
my (%ordered,$total,%jstext);
$total = scalar(keys(%{$settings}));
@@ -3270,6 +3447,7 @@ sub lti_javascript {
push(@jsarray,$ordered{$item});
}
my $jstext = ' var lti = Array('."'".join("','",@jsarray)."'".');'."\n";
+ my $linkprot_js = &Apache::courseprefs::linkprot_javascript();
return <<"ENDSCRIPT";
@@ -3619,16 +3916,16 @@ sub saml_javascript {
return <<"ENDSCRIPT";
-
-ENDSCRIPT
-}
-
sub print_autoenroll {
my ($dom,$settings,$rowtotal) = @_;
my $autorun = &Apache::lonnet::auto_run(undef,$dom),
@@ -4429,7 +4693,7 @@ sub print_contacts {
map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};
}
}
- foreach my $item ('errorthreshold','errorsysmail') {
+ foreach my $item ('errorthreshold','errorsysmail') {
$css_class = $rownum%2?' class="LC_odd_row"':'';
$datatable .= ''.
''.
@@ -4511,7 +4775,7 @@ sub print_contacts {
$includeloc{'override_'.$key} = '';
$includestr{'override_'.$key} = '';
if ($settings->{'overrides'}{$key}{'include'} ne '') {
- ($includeloc{'override_'.$key},$includestr{'override_'.$key}) =
+ ($includeloc{'override_'.$key},$includestr{'override_'.$key}) =
split(/:/,$settings->{'overrides'}{$key}{'include'},2);
$includestr{'override_'.$key} = &unescape($includestr{'override_'.$key});
}
@@ -4523,6 +4787,7 @@ sub print_contacts {
my $optionsprefix = 'LC_options_helpdesk_';
my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";
+
$datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
$numinrow,$othertitle,'overrides',
\$rownum,$onclicktypes,$customclass);
@@ -4589,7 +4854,7 @@ sub overridden_helpdesk {
}
my $title;
if (ref($short_titles) eq 'HASH') {
- $title = $short_titles->{$item};
+ $title = $short_titles->{$item};
}
$output .= ''.
'
@@ -4772,7 +5038,7 @@ sub print_helpsettings {
my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$num."_pos'".');"';
- $datatable .= ''.$role.' '.
+ $datatable .= ''.$role.' '.
'';
for (my $k=0; $k<=$maxnum; $k++) {
my $vpos = $k+1;
@@ -4811,7 +5077,7 @@ sub print_helpsettings {
&Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
my $chgstr = ' onchange="javascript:reorderHelpRoles(this.form,'."'helproles_".$count."_pos'".');"';
- $datatable .= ''.
+ $datatable .= ''.
' '."\n".
'';
for (my $k=0; $k<$maxnum+1; $k++) {
@@ -5092,7 +5358,7 @@ sub radiobutton_prefs {
foreach my $item (@{$toggles}) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .=
- ''.
+ ' '.
''.$choices->{$item}.
' ';
if ($align eq 'left') {
@@ -5121,50 +5387,421 @@ sub radiobutton_prefs {
}
sub print_ltitools {
- my ($position,$dom,$settings,$rowtotal) = @_;
- my (%rules,%encrypt,%privkeys,%linkprot);
+ my ($dom,$settings,$rowtotal) = @_;
+ my $rownum = 0;
+ my $css_class;
+ my $itemcount = 1;
+ my $maxnum = 0;
+ my %ordered;
if (ref($settings) eq 'HASH') {
- if ($position eq 'top') {
- if (exists($settings->{'encrypt'})) {
- if (ref($settings->{'encrypt'}) eq 'HASH') {
- foreach my $key (keys(%{$settings->{'encrypt'}})) {
- $encrypt{'toolsec_'.$key} = $settings->{'encrypt'}{$key};
+ foreach my $item (keys(%{$settings})) {
+ if (ref($settings->{$item}) eq 'HASH') {
+ my $num = $settings->{$item}{'order'};
+ $ordered{$num} = $item;
+ }
+ }
+ }
+ my $confname = $dom.'-domainconfig';
+ my $switchserver = &check_switchserver($dom,$confname);
+ my $maxnum = scalar(keys(%ordered));
+ my $datatable;
+ my %lt = <itools_names();
+ my @courseroles = ('cc','in','ta','ep','st');
+ my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
+ my @fields = ('fullname','firstname','lastname','email','roles','user');
+ if (keys(%ordered)) {
+ my @items = sort { $a <=> $b } keys(%ordered);
+ for (my $i=0; $i<@items; $i++) {
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $item = $ordered{$items[$i]};
+ my ($title,$key,$secret,$url,$lifetime,$imgsrc,%sigsel);
+ if (ref($settings->{$item}) eq 'HASH') {
+ $title = $settings->{$item}->{'title'};
+ $url = $settings->{$item}->{'url'};
+ $key = $settings->{$item}->{'key'};
+ $secret = $settings->{$item}->{'secret'};
+ $lifetime = $settings->{$item}->{'lifetime'};
+ my $image = $settings->{$item}->{'image'};
+ if ($image ne '') {
+ $imgsrc = ' ';
+ }
+ if ($settings->{$item}->{'sigmethod'} eq 'HMAC-256') {
+ $sigsel{'HMAC-256'} = ' selected="selected"';
+ } else {
+ $sigsel{'HMAC-SHA1'} = ' selected="selected"';
+ }
+ }
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_".$item."'".');"';
+ $datatable .= ''
+ .'';
+ for (my $k=0; $k<=$maxnum; $k++) {
+ my $vpos = $k+1;
+ my $selstr;
+ if ($k == $i) {
+ $selstr = ' selected="selected" ';
+ }
+ $datatable .= ''.$vpos.' ';
+ }
+ $datatable .= ' '.(' 'x2).
+ ' '.
+ &mt('Delete?').' '.
+ ''.
+ ''.&mt('Required settings').' '.
+ ''.$lt{'title'}.': '.
+ (' 'x2).
+ ''.$lt{'version'}.':'.
+ '1.1 '.
+ (' 'x2).
+ ''.$lt{'msgtype'}.':'.
+ 'Launch '.
+ (' 'x2).
+ ''.$lt{'sigmethod'}.':'.
+ 'HMAC-SHA1 '.
+ 'HMAC-SHA256 '.
+ ' '.
+ ''.$lt{'url'}.': '.
+ (' 'x2).
+ ''.$lt{'key'}.':'.
+ ' '.
+ (' 'x2).
+ ''.$lt{'lifetime'}.':'.
+ ' '.
+ (' 'x2).
+ ''.$lt{'secret'}.':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
+ ' '.
+ ' '.
+ ''.&mt('Optional settings').' '.
+ ''.&mt('Display target:');
+ my %currdisp;
+ if (ref($settings->{$item}->{'display'}) eq 'HASH') {
+ if ($settings->{$item}->{'display'}->{'target'} eq 'window') {
+ $currdisp{'window'} = ' checked="checked"';
+ } elsif ($settings->{$item}->{'display'}->{'target'} eq 'tab') {
+ $currdisp{'tab'} = ' checked="checked"';
+ } else {
+ $currdisp{'iframe'} = ' checked="checked"';
+ }
+ if ($settings->{$item}->{'display'}->{'width'} =~ /^(\d+)$/) {
+ $currdisp{'width'} = $1;
+ }
+ if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) {
+ $currdisp{'height'} = $1;
+ }
+ $currdisp{'linktext'} = $settings->{$item}->{'display'}->{'linktext'};
+ $currdisp{'explanation'} = $settings->{$item}->{'display'}->{'explanation'};
+ } else {
+ $currdisp{'iframe'} = ' checked="checked"';
+ }
+ foreach my $disp ('iframe','tab','window') {
+ $datatable .= ' '.
+ $lt{$disp}.' '.(' 'x2);
+ }
+ $datatable .= (' 'x4);
+ foreach my $dimen ('width','height') {
+ $datatable .= ''.$lt{$dimen}.' '.
+ ' '.
+ (' 'x2);
+ }
+ $datatable .= ' '.
+ ''.$lt{'linktext'}.' '.
+ '
'.
+ ''.$lt{'explanation'}.' '.
+ '
';
+ my %units = (
+ 'passback' => 'days',
+ 'roster' => 'seconds',
+ );
+ foreach my $extra ('passback','roster') {
+ my $validsty = 'none';
+ my $currvalid;
+ my $checkedon = '';
+ my $checkedoff = ' checked="checked"';
+ if ($settings->{$item}->{$extra}) {
+ $checkedon = $checkedoff;
+ $checkedoff = '';
+ $validsty = 'inline-block';
+ if ($settings->{$item}->{$extra.'valid'} =~ /^\d+\.?\d*$/) {
+ $currvalid = $settings->{$item}->{$extra.'valid'};
+ }
+ }
+ my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','$i'".');"';
+ $datatable .= ''.$lt{$extra}.' '.
+ ' '.
+ &mt('No').' '.(' 'x2).
+ ' '.
+ &mt('Yes').'
'.
+ '
';
+ }
+ $datatable .= ''.$lt{'icon'}.': ';
+ if ($imgsrc) {
+ $datatable .= $imgsrc.
+ ' '.&mt('Delete?').' '.
+ ' '.&mt('Replace:').' ';
+ } else {
+ $datatable .= '('.&mt('if larger than 21x21 pixels, image will be scaled').') ';
+ }
+ if ($switchserver) {
+ $datatable .= &mt('Upload to library server: [_1]',$switchserver);
+ } else {
+ $datatable .= ' ';
+ }
+ $datatable .= ' ';
+ my (%checkedfields,%rolemaps,$userincdom);
+ if (ref($settings->{$item}) eq 'HASH') {
+ if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
+ %checkedfields = %{$settings->{$item}->{'fields'}};
+ }
+ $userincdom = $settings->{$item}->{'incdom'};
+ if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
+ %rolemaps = %{$settings->{$item}->{'roles'}};
+ $checkedfields{'roles'} = 1;
+ }
+ }
+ $datatable .= ''.&mt('User data sent on launch').' '.
+ '';
+ my $userfieldstyle = 'display:none;';
+ my $seluserdom = '';
+ my $unseluserdom = ' selected="selected"';
+ foreach my $field (@fields) {
+ my ($checked,$onclick,$id,$spacer);
+ if ($checkedfields{$field}) {
+ $checked = ' checked="checked"';
+ }
+ if ($field eq 'user') {
+ $id = ' id="ltitools_user_field_'.$i.'"';
+ $onclick = ' onclick="toggleLTITools(this.form,'."'$field','$i'".')"';
+ if ($checked) {
+ $userfieldstyle = 'display:inline-block';
+ if ($userincdom) {
+ $seluserdom = $unseluserdom;
+ $unseluserdom = '';
+ }
}
+ } else {
+ $spacer = (' ' x2);
}
+ $datatable .= ''.
+ ' '.
+ $lt{$field}.' '.$spacer;
}
- if (exists($settings->{'private'})) {
- if (ref($settings->{'private'}) eq 'HASH') {
- if (ref($settings->{'private'}) eq 'HASH') {
- if (ref($settings->{'private'}{'keys'}) eq 'ARRAY') {
- map { $privkeys{$_} = 1; } (@{$settings->{'private'}{'keys'}});
+ $datatable .= ' ';
+ $datatable .= ''.
+ ' : '.
+ ''.
+ ''.&mt('Select').' '.
+ ''.&mt('username').' '.
+ ''.&mt('username:domain').' '.
+ '
';
+ $datatable .= ' '.
+ ''.&mt('Role mapping').' ';
+ foreach my $role (@courseroles) {
+ my ($selected,$selectnone);
+ if (!$rolemaps{$role}) {
+ $selectnone = ' selected="selected"';
+ }
+ $datatable .= ''.
+ &Apache::lonnet::plaintext($role,'Course').' '.
+ ''.
+ ''.&mt('Select').' ';
+ foreach my $ltirole (@ltiroles) {
+ unless ($selectnone) {
+ if ($rolemaps{$role} eq $ltirole) {
+ $selected = ' selected="selected"';
+ } else {
+ $selected = '';
}
}
+ $datatable .= ''.$ltirole.' ';
}
+ $datatable .= ' ';
}
- } elsif ($position eq 'middle') {
- if (exists($settings->{'rules'})) {
- if (ref($settings->{'rules'}) eq 'HASH') {
- %rules = %{$settings->{'rules'}};
+ $datatable .= '
';
+ my %courseconfig;
+ if (ref($settings->{$item}) eq 'HASH') {
+ if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
+ %courseconfig = %{$settings->{$item}->{'crsconf'}};
}
}
- } else {
- foreach my $key ('encrypt','private','rules') {
- if (exists($settings->{$key})) {
- delete($settings->{$key});
+ $datatable .= ''.&mt('Configurable in course').' ';
+ foreach my $item ('label','title','target','linktext','explanation','append') {
+ my $checked;
+ if ($courseconfig{$item}) {
+ $checked = ' checked="checked"';
}
+ $datatable .= ''.
+ ' '.
+ $lt{'crs'.$item}.' '."\n";
}
+ $datatable .= ' '.
+ ''.&mt('Custom items sent on launch').' '.
+ ' '."\n";
+ $itemcount ++;
}
}
- my $datatable;
- my $itemcount = 1;
- if ($position eq 'top') {
- $datatable = &secrets_form($dom,'toolsec',\%encrypt,\%privkeys,$rowtotal);
- } elsif ($position eq 'middle') {
- $datatable = &password_rules('toolsecrets',\$itemcount,\%rules);
- $$rowtotal += $itemcount;
- } else {
- $datatable = &Apache::courseprefs::print_ltitools($dom,'',$settings,\$rowtotal,'','','domain');
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_add_pos'".');"';
+ $datatable .= ''."\n".
+ ' '."\n".
+ '';
+ for (my $k=0; $k<$maxnum+1; $k++) {
+ my $vpos = $k+1;
+ my $selstr;
+ if ($k == $maxnum) {
+ $selstr = ' selected="selected" ';
+ }
+ $datatable .= ''.$vpos.' ';
}
+ $datatable .= ' '."\n".
+ ' '.&mt('Add').' '."\n".
+ ''.
+ ''.&mt('Required settings').' '.
+ ''.$lt{'title'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'version'}.':'.
+ '1.1 '."\n".
+ (' 'x2).
+ ''.$lt{'msgtype'}.':'.
+ 'Launch '.
+ ''.$lt{'sigmethod'}.':'.
+ 'HMAC-SHA1 '.
+ 'HMAC-SHA256 '.
+ ' '.
+ ''.$lt{'url'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'key'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'lifetime'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'secret'}.': '.
+ ' '.&mt('Visible input').' '."\n".
+ ' '.
+ ''.&mt('Optional settings').' '.
+ ''.&mt('Display target:');
+ my %defaultdisp;
+ $defaultdisp{'iframe'} = ' checked="checked"';
+ foreach my $disp ('iframe','tab','window') {
+ $datatable .= ' '.
+ $lt{$disp}.' '.(' 'x2);
+ }
+ $datatable .= (' 'x4);
+ foreach my $dimen ('width','height') {
+ $datatable .= ''.$lt{$dimen}.' '.
+ ' '.
+ (' 'x2);
+ }
+ $datatable .= ' '.
+ ''.$lt{'linktext'}.' '.
+ '
'.
+ ''.$lt{'explanation'}.' '.
+ ''.
+ '
';
+ my %units = (
+ 'passback' => 'days',
+ 'roster' => 'seconds',
+ );
+ my %defaulttimes = (
+ 'passback' => '7',
+ 'roster' => '300',
+ );
+ foreach my $extra ('passback','roster') {
+ my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','add'".');"';
+ $datatable .= ''.$lt{$extra}.' '.
+ ' '.
+ &mt('No').' '.(' 'x2).''.
+ ' '.
+ &mt('Yes').'
'.
+ '
';
+ }
+ $datatable .= ''.$lt{'icon'}.': '.
+ '('.&mt('if larger than 21x21 pixels, image will be scaled').') ';
+ if ($switchserver) {
+ $datatable .= &mt('Upload to library server: [_1]',$switchserver);
+ } else {
+ $datatable .= ' ';
+ }
+ $datatable .= ' '.
+ ''.&mt('User data sent on launch').' '.
+ '';
+ foreach my $field (@fields) {
+ my ($id,$onclick,$spacer);
+ if ($field eq 'user') {
+ $id = ' id="ltitools_user_field_add"';
+ $onclick = ' onclick="toggleLTITools(this.form,'."'$field','add'".')"';
+ } else {
+ $spacer = (' ' x2);
+ }
+ $datatable .= ''.
+ ' '.
+ $lt{$field}.' '.$spacer;
+ }
+ $datatable .= ' '.
+ ''.
+ ' : '.
+ ''.
+ ''.&mt('Select').' '.
+ ''.&mt('username').' '.
+ ''.&mt('username:domain').' '.
+ '
';
+ $datatable .= ''.&mt('Role mapping').' ';
+ foreach my $role (@courseroles) {
+ my ($checked,$checkednone);
+ $datatable .= ''.
+ &Apache::lonnet::plaintext($role,'Course').' '.
+ ''.
+ ''.&mt('Select').' ';
+ foreach my $ltirole (@ltiroles) {
+ $datatable .= ''.$ltirole.' ';
+ }
+ $datatable .= ' ';
+ }
+ $datatable .= '
'.
+ ''.&mt('Configurable in course').' ';
+ foreach my $item ('label','title','target','linktext','explanation','append') {
+ $datatable .= ''.
+ ' '.
+ $lt{'crs'.$item}.' '.(' ' x2)."\n";
+ }
+ $datatable .= ' '.
+ ''.&mt('Custom items sent on launch').' '.
+ ' '."\n".
+ ' '."\n".
+ ' '."\n";
+ $itemcount ++;
return $datatable;
}
@@ -5178,7 +5815,7 @@ sub ltitools_names {
'key' => 'Key',
'lifetime' => 'Nonce lifetime (s)',
'secret' => 'Secret',
- 'icon' => 'Icon',
+ 'icon' => 'Icon',
'user' => 'User',
'fullname' => 'Full Name',
'firstname' => 'First Name',
@@ -5196,7 +5833,7 @@ sub ltitools_names {
'roster' => 'Tool can retrieve roster:',
'crstarget' => 'Display target',
'crslabel' => 'Course label',
- 'crstitle' => 'Course title',
+ 'crstitle' => 'Course title',
'crslinktext' => 'Link Text',
'crsexplanation' => 'Explanation',
'crsappend' => 'Provider URL',
@@ -5204,128 +5841,645 @@ sub ltitools_names {
return %lt;
}
-sub secrets_form {
- my ($dom,$context,$encrypt,$privkeys,$rowtotal) = @_;
- my @ids=&Apache::lonnet::current_machine_ids();
- my %servers = &Apache::lonnet::get_servers($dom,'library');
- my $primary = &Apache::lonnet::domain($dom,'primary');
- my ($css_class,$extra,$numshown,$itemcount,$output);
- $itemcount = 0;
- foreach my $hostid (sort(keys(%servers))) {
- my ($showextra,$divsty,$switch);
- if ($hostid eq $primary) {
- if ($context eq 'ltisec') {
- if (($encrypt->{'ltisec_consumers'}) || ($encrypt->{'ltisec_domlinkprot'})) {
- $showextra = 1;
+sub print_proctoring {
+ my ($dom,$settings,$rowtotal) = @_;
+ my $itemcount = 1;
+ my (%ordered,%providernames,%current,%currentdef);
+ my $confname = $dom.'-domainconfig';
+ my $switchserver = &check_switchserver($dom,$confname);
+ if (ref($settings) eq 'HASH') {
+ foreach my $item (keys(%{$settings})) {
+ if (ref($settings->{$item}) eq 'HASH') {
+ my $num = $settings->{$item}{'order'};
+ $ordered{$num} = $item;
+ }
+ }
+ } else {
+ %ordered = (
+ 1 => 'proctorio',
+ 2 => 'examity',
+ );
+ }
+ %providernames = &proctoring_providernames();
+ my $maxnum = scalar(keys(%ordered));
+ my (%requserfields,%optuserfields,%defaults,%extended,%crsconf,@courseroles,@ltiroles);
+ my ($requref,$opturef,$defref,$extref,$crsref,$rolesref,$ltiref) = &proctoring_data();
+ if (ref($requref) eq 'HASH') {
+ %requserfields = %{$requref};
+ }
+ if (ref($opturef) eq 'HASH') {
+ %optuserfields = %{$opturef};
+ }
+ if (ref($defref) eq 'HASH') {
+ %defaults = %{$defref};
+ }
+ if (ref($extref) eq 'HASH') {
+ %extended = %{$extref};
+ }
+ if (ref($crsref) eq 'HASH') {
+ %crsconf = %{$crsref};
+ }
+ if (ref($rolesref) eq 'ARRAY') {
+ @courseroles = @{$rolesref};
+ }
+ if (ref($ltiref) eq 'ARRAY') {
+ @ltiroles = @{$ltiref};
+ }
+ my $datatable;
+ my $css_class;
+ if (keys(%ordered)) {
+ my @items = sort { $a <=> $b } keys(%ordered);
+ for (my $i=0; $i<@items; $i++) {
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $provider = $ordered{$items[$i]};
+ my $optionsty = 'none';
+ my ($available,$version,$lifetime,$imgsrc,$userincdom,$showroles,
+ %checkedfields,%rolemaps,%inuse,%crsconfig,%current);
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{$provider}) eq 'HASH') {
+ %current = %{$settings->{$provider}};
+ if ($current{'available'}) {
+ $optionsty = 'block';
+ $available = 1;
+ }
+ if ($current{'lifetime'} =~ /^\d+$/) {
+ $lifetime = $current{'lifetime'};
+ }
+ if ($current{'version'} =~ /^\d+\.\d+$/) {
+ $version = $current{'version'};
+ }
+ if ($current{'image'} ne '') {
+ $imgsrc = ' ';
+ }
+ if (ref($current{'fields'}) eq 'ARRAY') {
+ map { $checkedfields{$_} = 1; } @{$current{'fields'}};
+ }
+ $userincdom = $current{'incdom'};
+ if (ref($current{'roles'}) eq 'HASH') {
+ %rolemaps = %{$current{'roles'}};
+ $checkedfields{'roles'} = 1;
+ }
+ if (ref($current{'defaults'}) eq 'ARRAY') {
+ foreach my $val (@{$current{'defaults'}}) {
+ if (grep(/^\Q$val\E$/,@{$defaults{$provider}})) {
+ $inuse{$val} = 1;
+ } else {
+ foreach my $poss (keys(%{$extended{$provider}})) {
+ if (ref($extended{$provider}{$poss}) eq 'ARRAY') {
+ if (grep(/^\Q$val\E$/,@{$extended{$provider}{$poss}})) {
+ $inuse{$poss} = $val;
+ last;
+ }
+ }
+ }
+ }
+ }
+ } elsif (ref($current{'defaults'}) eq 'HASH') {
+ foreach my $key (keys(%{$current{'defaults'}})) {
+ my $currval = $current{'defaults'}{$key};
+ if (grep(/^\Q$key\E$/,@{$defaults{$provider}})) {
+ $inuse{$key} = 1;
+ } else {
+ my $match;
+ foreach my $poss (keys(%{$extended{$provider}})) {
+ if (ref($extended{$provider}{$poss}) eq 'ARRAY') {
+ if (grep(/^\Q$key\E$/,@{$extended{$provider}{$poss}})) {
+ $inuse{$poss} = $key;
+ last;
+ }
+ } elsif (ref($extended{$provider}{$poss}) eq 'HASH') {
+ foreach my $inner (sort(keys(%{$extended{$provider}{$poss}}))) {
+ if (ref($extended{$provider}{$poss}{$inner}) eq 'ARRAY') {
+ if (grep(/^\Q$currval\E$/,@{$extended{$provider}{$poss}{$inner}})) {
+ $currentdef{$inner} = $currval;
+ $match = 1;
+ last;
+ }
+ } elsif ($inner eq $key) {
+ $currentdef{$key} = $currval;
+ $match = 1;
+ last;
+ }
+ }
+ }
+ last if ($match);
+ }
+ }
+ }
+ }
+ if (ref($current{'crsconf'}) eq 'ARRAY') {
+ map { $crsconfig{$_} = 1; } @{$current{'crsconf'}};
+ }
}
- if ($encrypt->{'ltisec_crslinkprot'}) {
- $showextra = 1;
+ }
+ my %lt = &proctoring_titles($provider);
+ my %fieldtitles = &proctoring_fieldtitles($provider);
+ my $onclickavailable = ' onclick="toggleProctoring(this.form,'."'$provider'".');"';
+ my %checkedavailable = (
+ yes => '',
+ no => ' checked="checked"',
+ );
+ if ($available) {
+ $checkedavailable{'yes'} = $checkedavailable{'no'};
+ $checkedavailable{'no'} = '';
+ }
+ my $chgstr = ' onchange="javascript:reorderProctoring(this.form,'."'proctoring_pos_".$provider."'".');"';
+ $datatable .= ''
+ .'';
+ for (my $k=0; $k<$maxnum; $k++) {
+ my $vpos = $k+1;
+ my $selstr;
+ if ($k == $i) {
+ $selstr = ' selected="selected" ';
}
- } else {
- if (($encrypt->{'toolsec_crs'}) || ($encrypt->{'toolsec_dom'})) {
- $showextra = 1;
+ $datatable .= ''.$vpos.' ';
+ }
+ if ($version eq '') {
+ if ($provider eq 'proctorio') {
+ $version = '1.0';
+ } elsif ($provider eq 'examity') {
+ $version = '1.1';
}
}
- unless (grep(/^\Q$hostid\E$/,@ids)) {
- $switch = 1;
+ if ($lifetime eq '') {
+ $lifetime = '300';
}
- if ($showextra) {
- $numshown ++;
- $divsty = 'display:inline-block';
+ $datatable .=
+ ' '.(' 'x2).''.$providernames{$provider}.' '.
+ ''.$lt{'avai'}.' '.
+ ' '.&mt('Yes').' '."\n".
+ ' '.&mt('No').' '."\n".
+ ' '.
+ ''.
+ ''.$lt{'base'}.' '.
+ ''.$lt{'version'}.':'.
+ ''.$version.' '."\n".
+ (' 'x2).
+ ''.$lt{'sigmethod'}.':'.
+ 'HMAC-SHA1 '.
+ 'HMAC-SHA256 '.
+ (' 'x2).
+ ''.$lt{'lifetime'}.': '."\n".
+ ' '.
+ ''.$lt{'url'}.': '."\n".
+ ' '.
+ ''.$lt{'key'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'secret'}.': '.
+ ' '.$lt{'visible'}.' '."\n";
+ $datatable .= ''.$lt{'icon'}.': ';
+ if ($imgsrc) {
+ $datatable .= $imgsrc.
+ ' '.&mt('Delete?').' '.
+ ' '.&mt('Replace:');
+ }
+ $datatable .= ' ';
+ if ($switchserver) {
+ $datatable .= &mt('Upload to library server: [_1]',$switchserver);
} else {
- $divsty = 'display:none';
+ $datatable .= ' ';
}
- $extra .= ''.
- ''.$hostid.' ';
- if ($switch) {
- my $switchserver = ''.&mt('Switch Server').' ';
- if (exists($privkeys->{$hostid})) {
- $extra .= '
'.
- ''.
- &mt('Encryption Key').': ['.&mt('not shown').'] '.(' 'x2).' '.
- ''.&mt('Change?').
- ' '.&mt('No').' '.
- (' 'x2).
- ' '.&mt('Yes').
- '
'.
- ' - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).
- ' ';
- } else {
- $extra .= ''.
- &mt('Key required').' - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).
- ' '."\n";
+ unless ($imgsrc) {
+ $datatable .= ' ('.&mt('if larger than 21x21 pixels, image will be scaled').')';
+ }
+ $datatable .= ' '."\n";
+ if (ref($requserfields{$provider}) eq 'ARRAY') {
+ if (@{$requserfields{$provider}} > 0) {
+ $datatable .= ''.$lt{'requ'}.' ';
+ foreach my $field (@{$requserfields{$provider}}) {
+ $datatable .= ''.
+ ' '.
+ $lt{$field}.' ';
+ if ($field eq 'user') {
+ my $seluserdom = '';
+ my $unseluserdom = ' selected="selected"';
+ if ($userincdom) {
+ $seluserdom = $unseluserdom;
+ $unseluserdom = '';
+ }
+ $datatable .= ': '.
+ ''.
+ ''.$lt{'username'}.' '.
+ ''.$lt{'uname:dom'}.' '.
+ ' ';
+ } else {
+ $datatable .= ' ';
+ if ($field eq 'roles') {
+ $showroles = 1;
+ }
+ }
+ $datatable .= ' ';
+ }
}
- } elsif (exists($privkeys->{$hostid})) {
- $extra .= '
'.
- &mt('Encryption Key').': ['.&mt('not shown').'] '.(' 'x2).' '.
- ''.&mt('Change?').
- ' '.&mt('No').' '.
- (' 'x2).
- ' '.&mt('Yes').
- '
'.
- ''.&mt('New Key').':'.
- ' '.
- ' '.&mt('Visible input').' '.
- ' ';
- } else {
- $extra .= ''.&mt('Encryption Key').':'.
- ' '.
- ' '.&mt('Visible input').' ';
+ $datatable .= ' '."\n";
}
- $extra .= ' ';
+ if (ref($optuserfields{$provider}) eq 'ARRAY') {
+ if (@{$optuserfields{$provider}} > 0) {
+ $datatable .= ''.$lt{'optu'}.' ';
+ foreach my $field (@{$optuserfields{$provider}}) {
+ my $checked;
+ if ($checkedfields{$field}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= ''.
+ ' '.$lt{$field}.' ';
+ }
+ $datatable .= ' '."\n";
+ }
+ }
+ if (ref($defaults{$provider}) eq 'ARRAY') {
+ if (@{$defaults{$provider}}) {
+ my (%options,@selectboxes);
+ if (ref($extended{$provider}) eq 'HASH') {
+ %options = %{$extended{$provider}};
+ }
+ $datatable .= ''.$lt{'defa'}.' ';
+ my ($rem,$numinrow,$dropdowns);
+ if ($provider eq 'proctorio') {
+ $datatable .= '';
+ if (@selectboxes) {
+ $datatable .= '';
+ $numinrow = 2;
+ for (my $i=0; $i<@selectboxes; $i++) {
+ $rem = $i%($numinrow);
+ if ($rem == 0) {
+ if ($i > 0) {
+ $datatable .= '';
+ }
+ $datatable .= '';
+ }
+ $datatable .= ''.
+ $selectboxes[$i].' ';
+ }
+ if ($numinrow) {
+ $rem = $i%$numinrow;
+ }
+ $colsleft = $numinrow - $rem;
+ if ($colsleft > 1) {
+ $datatable .= '';
+ } else {
+ $datatable .= ' ';
+ }
+ $datatable .= ' '.
+ '
';
+ }
+ }
+ $datatable .= ' ';
+ }
+ if (ref($crsconf{$provider}) eq 'ARRAY') {
+ $datatable .= ''.
+ ''.&mt('Configurable in course').' ';
+ my ($rem,$numinrow);
+ if ($provider eq 'proctorio') {
+ $datatable .= '';
+ $numinrow = 4;
+ }
+ my $i = 0;
+ foreach my $item (@{$crsconf{$provider}}) {
+ my $name;
+ if ($provider eq 'examity') {
+ $name = $lt{'crs'.$item};
+ } elsif ($provider eq 'proctorio') {
+ $name = $fieldtitles{$item};
+ $rem = $i%($numinrow);
+ if ($rem == 0) {
+ if ($i > 0) {
+ $datatable .= '';
+ }
+ $datatable .= '';
+ }
+ $datatable .= ' '.
+ $name.'';
+ if ($provider eq 'examity') {
+ $datatable .= ' ';
+ }
+ $datatable .= "\n";
+ $i++;
+ }
+ if ($provider eq 'proctorio') {
+ if ($numinrow) {
+ $rem = $i%$numinrow;
+ }
+ my $colsleft = $numinrow - $rem;
+ if ($colsleft > 1) {
+ $datatable .= '';
+ } else {
+ $datatable .= ' ';
+ }
+ $datatable .= ' '.
+ '
';
+ }
+ $datatable .= ' ';
+ }
+ if ($showroles) {
+ $datatable .= ''.
+ ''.&mt('Role mapping').' ';
+ foreach my $role (@courseroles) {
+ my ($selected,$selectnone);
+ if (!$rolemaps{$role}) {
+ $selectnone = ' selected="selected"';
+ }
+ $datatable .= ''.
+ &Apache::lonnet::plaintext($role,'Course').' '.
+ ''.
+ ''.&mt('Select').' ';
+ foreach my $ltirole (@ltiroles) {
+ unless ($selectnone) {
+ if ($rolemaps{$role} eq $ltirole) {
+ $selected = ' selected="selected"';
+ } else {
+ $selected = '';
+ }
+ }
+ $datatable .= ''.$ltirole.' ';
+ }
+ $datatable .= ' ';
+ }
+ $datatable .= '
'.
+ ''.
+ ''.&mt('Custom items sent on launch').' '.
+ ' '."\n";
+ }
+ $datatable .= ' ';
+ }
+ $itemcount ++;
}
}
- my (%choices,@toggles,%defaultchecked);
- if ($context eq 'ltisec') {
- %choices = &Apache::lonlocal::texthash (
- ltisec_crslinkprot => 'Encrypt stored link protection secrets defined in courses',
- ltisec_domlinkprot => 'Encrypt stored link protection secrets defined in domain',
- ltisec_consumers => 'Encrypt stored consumer secrets defined in domain',
- );
- @toggles = qw(ltisec_crslinkprot ltisec_domlinkprot ltisec_consumers);
- %defaultchecked = (
- 'ltisec_crslinkprot' => 'off',
- 'ltisec_domlinkprot' => 'off',
- 'ltisec_consumers' => 'off',
- );
- } else {
- %choices = &Apache::lonlocal::texthash (
- toolsec_crs => 'Encrypt stored external tool secrets defined in courses',
- toolsec_dom => 'Encrypt stored external tool secrets defined in domain',
- );
- @toggles = qw(toolsec_crs toolsec_dom);
- %defaultchecked = (
- 'toolsec_crs' => 'off',
- 'toolsec_dom' => 'off',
- );
+ return $datatable;
+}
+
+sub proctoring_data {
+ my $requserfields = {
+ proctorio => ['user'],
+ examity => ['roles','user'],
+ };
+ my $optuserfields = {
+ proctorio => ['fullname'],
+ examity => ['fullname','firstname','lastname','email'],
+ };
+ my $defaults = {
+ proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic',
+ 'recordroomstart','verifyvideo','verifyaudio','verifydesktop',
+ 'verifyid','verifysignature','fullscreen','clipboard','tabslinks',
+ 'closetabs','onescreen','print','downloads','cache','rightclick',
+ 'reentry','calculator','whiteboard'],
+ examity => ['display'],
+ };
+ my $extended = {
+ proctorio => {
+ verifyid => ['verifyidauto','verifyidlive'],
+ fullscreen => ['fullscreenlenient','fullscreenmoderate','fullscreensever'],
+ tabslinks => ['notabs','linksonly'],
+ reentry => ['noreentry','agentreentry'],
+ calculator => ['calculatorbasic','calculatorsci'],
+ },
+ examity => {
+ display => {
+ target => ['iframe','tab','window'],
+ width => '',
+ height => '',
+ linktext => '',
+ explanation => '',
+ },
+ },
+ };
+ my $crsconf = {
+ proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic',
+ 'recordroomstart','verifyvideo','verifyaudio','verifydesktop',
+ 'verifyid','verifysignature','fullscreen','clipboard','tabslinks',
+ 'closetabs','onescreen','print','downloads','cache','rightclick',
+ 'reentry','calculator','whiteboard'],
+ examity => ['label','title','target','linktext','explanation','append'],
+ };
+ my $courseroles = ['cc','in','ta','ep','st'];
+ my $ltiroles = ['Instructor','ContentDeveloper','TeachingAssistant','Learner'];
+ return ($requserfields,$optuserfields,$defaults,$extended,$crsconf,$courseroles,$ltiroles);
+}
+
+sub proctoring_titles {
+ my ($item) = @_;
+ my (%common_lt,%custom_lt);
+ %common_lt = &Apache::lonlocal::texthash (
+ 'avai' => 'Available?',
+ 'base' => 'Basic Settings',
+ 'requ' => 'User data required to be sent on launch',
+ 'optu' => 'User data optionally sent on launch',
+ 'udsl' => 'User data sent on launch',
+ 'defa' => 'Defaults for items configurable in course',
+ 'sigmethod' => 'Signature Method',
+ 'key' => 'Key',
+ 'lifetime' => 'Nonce lifetime (s)',
+ 'secret' => 'Secret',
+ 'icon' => 'Icon',
+ 'fullname' => 'Full Name',
+ 'visible' => 'Visible input',
+ 'username' => 'username',
+ 'user' => 'User',
+ );
+ if ($item eq 'proctorio') {
+ %custom_lt = &Apache::lonlocal::texthash (
+ 'version' => 'OAuth version',
+ 'url' => 'API URL',
+ 'uname:dom' => 'username-domain',
+ );
+ } elsif ($item eq 'examity') {
+ %custom_lt = &Apache::lonlocal::texthash (
+ 'version' => 'LTI Version',
+ 'url' => 'URL',
+ 'uname:dom' => 'username:domain',
+ 'msgtype' => 'Message Type',
+ 'firstname' => 'First Name',
+ 'lastname' => 'Last Name',
+ 'email' => 'E-mail',
+ 'roles' => 'Role',
+ 'crstarget' => 'Display target',
+ 'crslabel' => 'Course label',
+ 'crstitle' => 'Course title',
+ 'crslinktext' => 'Link Text',
+ 'crsexplanation' => 'Explanation',
+ 'crsappend' => 'Provider URL',
+ );
}
- my ($onclick,$itemcount);
- $onclick = 'javascript:toggleLTIEncKey(this.form,'."'$context'".');';
- ($output,$itemcount) = &radiobutton_prefs($encrypt,\@toggles,\%defaultchecked,
- \%choices,$itemcount,$onclick,'','left','no');
+ my %lt = (%common_lt,%custom_lt);
+ return %lt;
+}
- $css_class = $itemcount%2?' class="LC_odd_row"':'';
- my $noprivkeysty = 'display:inline-block';
- if ($numshown) {
- $noprivkeysty = 'display:none';
- }
- $output .= ''.&mt('Encryption Key(s)').' '.
- ''.
- ''.&mt('Not in use').'
'.
- $extra.
- ' ';
- $itemcount ++;
- $$rowtotal += $itemcount;
- return $output;
+sub proctoring_fieldtitles {
+ my ($item) = @_;
+ if ($item eq 'proctorio') {
+ return &Apache::lonlocal::texthash (
+ 'recordvideo' => 'Record video',
+ 'recordaudio' => 'Record audio',
+ 'recordscreen' => 'Record screen',
+ 'recordwebtraffic' => 'Record web traffic',
+ 'recordroomstart' => 'Record room scan',
+ 'verifyvideo' => 'Verify webcam',
+ 'verifyaudio' => 'Verify microphone',
+ 'verifydesktop' => 'Verify desktop recording',
+ 'verifyid' => 'Photo ID verification',
+ 'verifysignature' => 'Require signature',
+ 'fullscreen' => 'Fullscreen',
+ 'clipboard' => 'Disable copy/paste',
+ 'tabslinks' => 'New tabs/windows',
+ 'closetabs' => 'Close other tabs',
+ 'onescreen' => 'Limit to single screen',
+ 'print' => 'Disable Printing',
+ 'downloads' => 'Disable Downloads',
+ 'cache' => 'Empty cache after exam',
+ 'rightclick' => 'Disable right click',
+ 'reentry' => 'Re-entry to exam',
+ 'calculator' => 'Onscreen calculator',
+ 'whiteboard' => 'Onscreen whiteboard',
+ 'verifyidauto' => 'Automated verification',
+ 'verifyidlive' => 'Live agent verification',
+ 'fullscreenlenient' => 'Forced, but can navigate away for up to 30s',
+ 'fullscreenmoderate' => 'Forced, but can navigate away for up to 15s',
+ 'fullscreensever' => 'Forced, navigation away ends exam',
+ 'notabs' => 'Disaallowed',
+ 'linksonly' => 'Allowed from links in exam',
+ 'noreentry' => 'Disallowed',
+ 'agentreentry' => 'Agent required for re-entry',
+ 'calculatorbasic' => 'Basic',
+ 'calculatorsci' => 'Scientific',
+ );
+ } elsif ($item eq 'examity') {
+ return &Apache::lonlocal::texthash (
+ 'target' => 'Display target',
+ 'window' => 'Window',
+ 'tab' => 'Tab',
+ 'iframe' => 'iFrame',
+ 'height' => 'Height (pixels)',
+ 'width' => 'Width (pixels)',
+ 'linktext' => 'Default Link Text',
+ 'explanation' => 'Default Explanation',
+ 'append' => 'Provider URL',
+ );
+ }
+}
+
+sub proctoring_providernames {
+ return (
+ proctorio => 'Proctorio',
+ examity => 'Examity',
+ );
}
sub print_lti {
my ($position,$dom,$settings,$rowtotal) = @_;
my $itemcount = 1;
my ($datatable,$css_class);
- my (%rules,%encrypt,%privkeys,%linkprot,%suggestions);
+ my (%rules,%encrypt,%privkeys,%linkprot);
if (ref($settings) eq 'HASH') {
if ($position eq 'top') {
if (exists($settings->{'encrypt'})) {
@@ -5348,18 +6502,12 @@ sub print_lti {
}
}
}
- } elsif ($position eq 'upper') {
+ } elsif ($position eq 'middle') {
if (exists($settings->{'rules'})) {
if (ref($settings->{'rules'}) eq 'HASH') {
%rules = %{$settings->{'rules'}};
}
}
- } elsif ($position eq 'middle') {
- if (exists($settings->{'suggested'})) {
- if (ref($settings->{'suggested'}) eq 'HASH') {
- %suggestions = %{$settings->{'suggested'}};
- }
- }
} elsif ($position eq 'lower') {
if (exists($settings->{'linkprot'})) {
if (ref($settings->{'linkprot'}) eq 'HASH') {
@@ -5370,7 +6518,7 @@ sub print_lti {
}
}
} else {
- foreach my $key ('encrypt','private','rules','linkprot','suggestions') {
+ foreach my $key ('encrypt','private','rules','linkprot') {
if (exists($settings->{$key})) {
delete($settings->{$key});
}
@@ -5378,19 +6526,104 @@ sub print_lti {
}
}
if ($position eq 'top') {
- $datatable = &secrets_form($dom,'ltisec',\%encrypt,\%privkeys,$rowtotal);
- } elsif ($position eq 'upper') {
- $datatable = &password_rules('ltisecrets',\$itemcount,\%rules);
+ my @ids=&Apache::lonnet::current_machine_ids();
+ my %servers = &Apache::lonnet::get_servers($dom,'library');
+ my $primary = &Apache::lonnet::domain($dom,'primary');
+ my ($extra,$numshown);
+ foreach my $hostid (sort(keys(%servers))) {
+ my ($showextra,$divsty,$switch);
+ if ($hostid eq $primary) {
+ if (($encrypt{'ltisec_consumers'}) || ($encrypt{'ltisec_domlinkprot'})) {
+ $showextra = 1;
+ }
+ }
+ if ($encrypt{'ltisec_crslinkprot'}) {
+ $showextra = 1;
+ }
+ unless (grep(/^\Q$hostid\E$/,@ids)) {
+ $switch = 1;
+ }
+ if ($showextra) {
+ $numshown ++;
+ $divsty = 'display:inline-block';
+ } else {
+ $divsty = 'display:none';
+ }
+ $extra .= ''.
+ ''.$hostid.' ';
+ if ($switch) {
+ my $switchserver = ''.&mt('Switch Server').' ';
+ if (exists($privkeys{$hostid})) {
+ $extra .= '
'.
+ ''.
+ &mt('Encryption Key').': ['.&mt('not shown').'] '.(' 'x2).' '.
+ ''.&mt('Change?').
+ ' '.&mt('No').' '.
+ (' 'x2).
+ ' '.&mt('Yes').
+ '
'.
+ ' - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).
+ ' ';
+ } else {
+ $extra .= ''.
+ &mt('Key required').' - '.&mt('submit from server ([_1]): [_2].',$hostid,$switchserver).
+ ' '."\n";
+ }
+ } elsif (exists($privkeys{$hostid})) {
+ $extra .= '
'.
+ &mt('Encryption Key').': ['.&mt('not shown').'] '.(' 'x2).' '.
+ ''.&mt('Change?').
+ ' '.&mt('No').' '.
+ (' 'x2).
+ ' '.&mt('Yes').
+ '
'.
+ ''.&mt('New Key').':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
+ ' ';
+ } else {
+ $extra .= ''.&mt('Encryption Key').':'.
+ ' '.
+ ' '.&mt('Visible input').' ';
+ }
+ $extra .= ' ';
+ }
+ my %choices = &Apache::lonlocal::texthash (
+ ltisec_crslinkprot => 'Encrypt stored link protection secrets defined in courses',
+ ltisec_domlinkprot => 'Encrypt stored link protection secrets defined in domain',
+ ltisec_consumers => 'Encrypt stored consumer secrets defined in domain',
+ );
+ my @toggles = qw(ltisec_crslinkprot ltisec_domlinkprot ltisec_consumers);
+ my %defaultchecked = (
+ 'ltisec_crslinkprot' => 'off',
+ 'ltisec_domlinkprot' => 'off',
+ 'ltisec_consumers' => 'off',
+ );
+ my ($onclick,$itemcount);
+ $onclick = 'javascript:toggleLTIEncKey(this.form);';
+ ($datatable,$itemcount) = &radiobutton_prefs(\%encrypt,\@toggles,\%defaultchecked,
+ \%choices,$itemcount,$onclick,'','left','no');
+
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $noprivkeysty = 'display:inline-block';
+ if ($numshown) {
+ $noprivkeysty = 'display:none';
+ }
+ $datatable .= ''.&mt('Encryption Key(s)').' '.
+ ''.
+ ''.&mt('Not in use').'
'.
+ $extra.
+ ' ';
+ $itemcount ++;
$$rowtotal += $itemcount;
} elsif ($position eq 'middle') {
- $datatable = &linkprot_suggestions(\%suggestions,\$itemcount);
+ $datatable = &password_rules('secrets',\$itemcount,\%rules);
$$rowtotal += $itemcount;
} elsif ($position eq 'lower') {
- $datatable .= &Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain');
+ $datatable .= &Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain');
} else {
- my ($switchserver,$switchmessage);
- $switchserver = &check_switchserver($dom);
- $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver);
my $maxnum = 0;
my %ordered;
if (ref($settings) eq 'HASH') {
@@ -5411,10 +6644,10 @@ sub print_lti {
for (my $i=0; $i<@items; $i++) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $item = $ordered{$items[$i]};
- my ($key,$secret,$usable,$lifetime,$consumer,$requser,$crsinc,$current);
+ my ($key,$secret,$lifetime,$consumer,$requser,$crsinc,$current);
if (ref($settings->{$item}) eq 'HASH') {
$key = $settings->{$item}->{'key'};
- $usable = $settings->{$item}->{'usable'};
+ $secret = $settings->{$item}->{'secret'};
$lifetime = $settings->{$item}->{'lifetime'};
$consumer = $settings->{$item}->{'consumer'};
$requser = $settings->{$item}->{'requser'};
@@ -5462,56 +6695,8 @@ sub print_lti {
'1.1 '.
(' 'x2).
''.$lt{'lifetime'}.': ';
- if ($key ne '') {
- $datatable .= ''.$lt{'key'};
- if ($switchserver) {
- $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']';
- } else {
- $datatable .= ': ';
- }
- $datatable .= ' '.(' 'x2);
- } elsif (!$switchserver) {
- $datatable .= ''.$lt{'key'}.':'.
- ' '.
- ' '.(' 'x2);
- }
- if ($switchserver) {
- if ($usable ne '') {
- $datatable .= '
'.
- $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).' '.
- ''.&mt('Change secret?').
- ' '.&mt('No').' '.
- (' 'x2).
- ' '.&mt('Yes').' '.(' 'x2).
- '
'.
- ' - '.$switchmessage.' '.
- '';
- } elsif ($key eq '') {
- $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.' '."\n";
- } else {
- $datatable .= ''.&mt('Secret required').' - '.$switchmessage.' '."\n";
- }
- } else {
- if ($usable ne '') {
- $datatable .= '
'.
- $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).' '.
- ''.&mt('Change?').
- ' '.&mt('No').' '.
- (' 'x2).
- ' '.&mt('Yes').
- '
'.
- ''.&mt('New Secret').':'.
- ' '.
- ' '.&mt('Visible input').' ';
- } else {
- $datatable .=
- ''.$lt{'secret'}.':'.
- ' '.
- ' '.&mt('Visible input').' ';
- }
- }
- $datatable .= ' '.
+ 'value="'.$lifetime.'" size="3" /> '.
+ (' 'x2).
''.$lt{'requser'}.':'.
' '.&mt('Yes').' '."\n".
' '.&mt('No').' '."\n".
@@ -5520,6 +6705,12 @@ sub print_lti {
' '.&mt('Yes').' '."\n".
' '.&mt('No').' '."\n".
(' 'x4).
+ ''.$lt{'key'}.
+ ': '.
+ (' 'x2).
+ ''.$lt{'secret'}.':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
' '.
''.<i_options($i,$current,$itemcount,%lt).' ';
$itemcount ++;
@@ -5548,16 +6739,8 @@ sub print_lti {
''.$lt{'version'}.':'.
'1.1 '."\n".
(' 'x2).
- ''.$lt{'lifetime'}.': '."\n";
- if ($switchserver) {
- $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.' '."\n";
- } else {
- $datatable .= ''.$lt{'key'}.': '."\n".
- (' 'x2).
- ''.$lt{'secret'}.': '.
- ' '.&mt('Visible input').' '."\n";
- }
- $datatable .= ' '.
+ ''.$lt{'lifetime'}.': '."\n".
+ (' 'x2).
''.$lt{'requser'}.':'.
' '.&mt('Yes').' '."\n".
' '.&mt('No').' '."\n".
@@ -5565,6 +6748,11 @@ sub print_lti {
''.$lt{'crsinc'}.':'.
' '.&mt('Yes').' '."\n".
' '.&mt('No').' '."\n".
+ (' 'x4).
+ ''.$lt{'key'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'secret'}.': '.
+ ' '.&mt('Visible input').' '."\n".
''.<i_options('add',undef,$itemcount,%lt).
' '."\n".
' '."\n";
@@ -5637,7 +6825,7 @@ sub lti_options {
if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
$checked{'mapuser'}{'sourcedid'} = '';
if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') {
- $checked{'mapuser'}{'email'} = ' checked="checked"';
+ $checked{'mapuser'}{'email'} = ' checked="checked"';
} else {
$checked{'mapuser'}{'other'} = ' checked="checked"';
$userfield = $current->{'mapuser'};
@@ -5647,7 +6835,7 @@ sub lti_options {
if (($current->{'mapcrs'} ne '') && ($current->{'mapcrs'} ne 'course_offering_sourcedid')) {
$checked{'mapcrs'}{'course_offering_sourcedid'} = '';
if ($current->{'mapcrs'} eq 'context_id') {
- $checked{'mapcrs'}{'context_id'} = ' checked="checked"';
+ $checked{'mapcrs'}{'context_id'} = ' checked="checked"';
} else {
$checked{'mapcrs'}{'other'} = ' checked="checked"';
$cidfield = $current->{'mapcrs'};
@@ -5675,7 +6863,7 @@ sub lti_options {
$checked{'lcauth'}{$1} = ' checked="checked"';
unless (($current->{'lcauth'} eq 'lti') || ($current->{'lcauth'} eq 'internal')) {
$lcauthparm = $current->{'lcauthparm'};
- $lcauthparmstyle = 'display:table-row';
+ $lcauthparmstyle = 'display:table-row';
if ($current->{'lcauth'} eq 'localauth') {
$lcauthparmtext = &mt('Local auth argument');
} else {
@@ -5692,7 +6880,7 @@ sub lti_options {
%rolemaps = %{$current->{'maproles'}};
}
if ($current->{'section'} ne '') {
- $checked{'crssec'}{'Y'} = ' checked="checked"';
+ $checked{'crssec'}{'Y'} = ' checked="checked"';
$crssecfieldsty = 'inline-block';
if ($current->{'section'} eq 'course_section_sourcedid') {
$checked{'crssecsrc'}{'sourcedid'} = ' checked="checked"';
@@ -5738,16 +6926,17 @@ sub lti_options {
$checked{'crssec'}{'N'} = ' checked="checked"';
$checked{'callback'}{'N'} = ' checked="checked"';
$checked{'topmenu'}{'N'} = ' checked="checked"';
- $checked{'inlinemenu'}{'Y'} = ' checked="checked"';
+ $checked{'inlinemenu'}{'Y'} = ' checked="checked"';
$checked{'menuitem'}{'grades'} = ' checked="checked"';
- $menusty = 'inline-block';
+ $menusty = 'inline-block';
}
- my @coursetypes = ('official','unofficial','community','textbook','lti');
+ my @coursetypes = ('official','unofficial','community','textbook','placement','lti');
my %coursetypetitles = &Apache::lonlocal::texthash (
official => 'Official',
unofficial => 'Unofficial',
community => 'Community',
textbook => 'Textbook',
+ placement => 'Placement Test',
lti => 'LTI Provider',
);
my @authtypes = ('internal','krb4','krb5','localauth');
@@ -5792,7 +6981,7 @@ sub lti_options {
''.&mt('Roles which may create user accounts').' ';
foreach my $ltirole (@ltiroles) {
$output .= ' '.$ltirole.' ';
+ $checked{'makeuser'}{$ltirole}.' />'.$ltirole.' ';
}
$output .= ''.
''.&mt('New user accounts created for LTI users').' '.
@@ -5924,9 +7113,9 @@ sub lti_options {
if ($extra eq 'passback') {
$pb1p1chk = ' checked="checked"';
$pb1p0chk = '';
- $onclickpb = ' onclick="toggleLTI(this.form,'."'passback','$num'".');"';
+ $onclickpb = ' onclick="toggleLTI(this.form,'."'passback','$num'".');"';
} else {
- $onclickpb = '';
+ $onclickpb = '';
}
if (ref($current) eq 'HASH') {
if (($current->{$extra})) {
@@ -5972,56 +7161,20 @@ sub ltimenu_titles {
);
}
-sub linkprot_suggestions {
- my ($suggested,$itemcount) = @_;
- my $count = 0;
- my $next = 1;
- my %lt = &Apache::lonlocal::texthash(
- 'name' => 'Suggested Launcher',
- 'info' => 'Recommendations',
- );
- my ($datatable,$css_class,$dest);
- if (ref($suggested) eq 'HASH') {
- my @current = sort { $a <=> $b } keys(%{$suggested});
- $next += $current[-1];
- for (my $i=0; $i<@current; $i++) {
- my $num = $current[$i];
- my %values;
- if (ref($suggested->{$num}) eq 'HASH') {
- %values = %{$suggested->{$num}};
- } else {
- next;
- }
- $css_class = $$itemcount%2?' class="LC_odd_row"':'';
- $datatable .=
- ''."\n".
- ' '."\n".
- &mt('Delete?').' '."\n".
- '
'.$lt{'name'}.' '."\n".
- ' '."\n".
- ' '.
- '
'.$lt{'info'}.' '."\n".
- ''.
- ' '.
- '
'."\n".
- ' '."\n";
- $$itemcount ++;
+sub check_switchserver {
+ my ($home) = @_;
+ my $switchserver;
+ if ($home ne '') {
+ my $allowed;
+ my @ids=&Apache::lonnet::current_machine_ids();
+ foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
+ if (!$allowed) {
+ $switchserver=''.&mt('Switch Server').' ';
}
}
- $css_class = $$itemcount%2?' class="LC_odd_row"':'';
- $datatable .= ''."\n".
- ' '."\n".
- ' '.&mt('Add').' '."\n".
- ''."\n".
- '
'.$lt{'name'}.' '."\n".
- ' '."\n".
- ' '.
- '
'.$lt{'info'}.' '."\n".
- ''.
- ' '.
- '
'."\n".
- ' '."\n";
- return $datatable;
+ return $switchserver;
}
sub print_coursedefaults {
@@ -6029,8 +7182,8 @@ sub print_coursedefaults {
my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
my $itemcount = 1;
my %choices = &Apache::lonlocal::texthash (
+ canuse_pdfforms => 'Course/Community users can create/upload PDF forms',
uploadquota => 'Default quota for files uploaded directly to course/community using Course Editor (MB)',
- coursequota => 'Default cumulative quota for all group portfolio spaces in course (MB)',
anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys',
coursecredits => 'Credits can be specified for courses',
uselcmath => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)',
@@ -6041,28 +7194,22 @@ sub print_coursedefaults {
canclone => "People who may clone a course (besides course's owner and coordinators)",
mysqltables => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',
ltiauth => 'Student username in LTI launch of deep-linked URL can be accepted without re-authentication',
- domexttool => 'External Tools defined in the domain may be used in courses/communities (by type)',
- exttool => 'External Tools can be defined and configured in courses/communities (by type)',
- crseditors => 'Available editors for web pages and/or problems created in a course/community',
);
my %staticdefaults = (
anonsurvey_threshold => 10,
uploadquota => 500,
- coursequota => 20,
postsubmit => 60,
mysqltables => 172800,
- domexttool => 1,
- exttool => 0,
- crseditors => ['edit','xml'],
);
if ($position eq 'top') {
%defaultchecked = (
+ 'canuse_pdfforms' => 'off',
'uselcmath' => 'on',
'usejsme' => 'on',
'inline_chem' => 'on',
'canclone' => 'none',
);
- @toggles = ('uselcmath','usejsme','inline_chem');
+ @toggles = ('canuse_pdfforms','uselcmath','usejsme','inline_chem');
my $deftex = $Apache::lonnet::deftex;
if (ref($settings) eq 'HASH') {
if ($settings->{'texengine'}) {
@@ -6095,7 +7242,7 @@ sub print_coursedefaults {
$datatable = $mathdisp.$datatable;
$css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .=
- ''.
+ ' '.
''.$choices{'canclone'}.
' ';
my $currcanclone = 'none';
@@ -6166,59 +7313,21 @@ sub print_coursedefaults {
$itemcount ++;
} else {
$css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
- my ($currdefresponder,%defcredits,%curruploadquota,%currcoursequota,
- %deftimeout,%currmysql);
+ my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql);
my $currusecredits = 0;
my $postsubmitclient = 1;
my $ltiauth = 0;
- my %domexttool;
- my %exttool;
- my %crseditors;
- my @types = ('official','unofficial','community','textbook');
+ my @types = ('official','unofficial','community','textbook','placement');
if (ref($settings) eq 'HASH') {
if ($settings->{'ltiauth'}) {
$ltiauth = 1;
}
- if (ref($settings->{'domexttool'}) eq 'HASH') {
- foreach my $type (@types) {
- if ($settings->{'domexttool'}->{$type}) {
- $domexttool{$type} = ' checked="checked"';
- }
- }
- } else {
- foreach my $type (@types) {
- if ($staticdefaults{'domexttool'}) {
- $domexttool{$type} = ' checked="checked"';
- }
- }
- }
- if (ref($settings->{'exttool'}) eq 'HASH') {
- foreach my $type (@types) {
- if ($settings->{'exttool'}->{$type}) {
- $exttool{$type} = ' checked="checked"';
- }
- }
- }
- if (ref($settings->{'crseditors'}) eq 'ARRAY') {
- foreach my $editor (@{$settings->{'crseditors'}}) {
- $crseditors{$editor} = ' checked="checked"';
- }
- } else {
- foreach my $editor (@{$staticdefaults{'crseditors'}}) {
- $crseditors{$editor} = ' checked="checked"';
- }
- }
$currdefresponder = $settings->{'anonsurvey_threshold'};
if (ref($settings->{'uploadquota'}) eq 'HASH') {
foreach my $type (keys(%{$settings->{'uploadquota'}})) {
$curruploadquota{$type} = $settings->{'uploadquota'}{$type};
}
}
- if (ref($settings->{'coursequota'}) eq 'HASH') {
- foreach my $type (keys(%{$settings->{'coursequota'}})) {
- $currcoursequota{$type} = $settings->{'coursequota'}{$type};
- }
- }
if (ref($settings->{'coursecredits'}) eq 'HASH') {
foreach my $type (@types) {
next if ($type eq 'community');
@@ -6264,12 +7373,6 @@ sub print_coursedefaults {
} else {
foreach my $type (@types) {
$deftimeout{$type} = $staticdefaults{'postsubmit'};
- if ($staticdefaults{'domexttool'}) {
- $domexttool{$type} = ' checked="checked"';
- }
- }
- foreach my $editor (@{$staticdefaults{'crseditors'}}) {
- $crseditors{$editor} = ' checked="checked"';
}
}
if (!$currdefresponder) {
@@ -6281,9 +7384,6 @@ sub print_coursedefaults {
if ($curruploadquota{$type} eq '') {
$curruploadquota{$type} = $staticdefaults{'uploadquota'};
}
- if ($currcoursequota{$type} eq '') {
- $currcoursequota{$type} = $staticdefaults{'coursequota'};
- }
}
$datatable .=
' '.
@@ -6298,25 +7398,12 @@ sub print_coursedefaults {
$datatable .= ''.
$choices{'uploadquota'}.
' '.
- ''.
- ' '."\n";
- $itemcount ++;
- $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
- $datatable .= ''.
- $choices{'coursequota'}.
- ' '.
''.
' '."\n";
$itemcount ++;
@@ -6329,7 +7416,7 @@ sub print_coursedefaults {
''.&mt('Default credits').' ';
foreach my $type (@types) {
next if ($type eq 'community');
- $additional .= ''.&mt($type).' '.
+ $additional .= ' '.&mt($type).' '.
' ';
}
@@ -6353,7 +7440,7 @@ sub print_coursedefaults {
''.&mt('Enter 0 to remain disabled until page reload.').' '.
'';
foreach my $type (@types) {
- $additional .= ''.&mt($type).' '.
+ $additional .= ' '.&mt($type).' '.
' ';
}
@@ -6371,10 +7458,10 @@ sub print_coursedefaults {
$datatable .= ' '.
$choices{'mysqltables'}.
' '.
- ''.
+ ' '.
'';
foreach my $type (@types) {
- $datatable .= ''.&mt($type).' '.
+ $datatable .= ' '.&mt($type).' '.
' ';
}
@@ -6389,290 +7476,17 @@ sub print_coursedefaults {
&radiobutton_prefs($current,\@toggles,\%defaultchecked,
\%choices,$itemcount,undef,undef,'left');
$datatable .= $table;
- $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
- $datatable .= ' '.
- $choices{'domexttool'}.
- ' '.
- ''.
- ' '."\n";
- $itemcount ++;
- $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
- $datatable .= ''.
- $choices{'exttool'}.
- ' '.
- ''.
- ' '."\n";
- $itemcount ++;
- $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
- $datatable .= ''.
- $choices{'crseditors'}.
- ' '.
- ''.
- ' '."\n";
- }
- $$rowtotal += $itemcount;
- return $datatable;
-}
-
-sub crseditor_titles {
- return &Apache::lonlocal::texthash(
- edit => 'Standard editor (Edit)',
- xml => 'Text editor (EditXML)',
- daxe => 'Daxe editor (Daxe)',
- );
-}
-
-sub print_authordefaults {
- my ($position,$dom,$settings,$rowtotal) = @_;
- my ($css_class,$datatable,%checkedon,%checkedoff);
- my $itemcount = 1;
- my %titles = &authordefaults_titles();
- if ($position eq 'top') {
- my %defaultchecked = (
- 'nocodemirror' => 'off',
- 'daxecollapse' => 'off',
- 'domcoordacc' => 'on',
- );
- my @toggles = ('nocodemirror','daxecollapse','domcoordacc');
- ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked,
- \%titles,$itemcount);
- my %staticdefaults = (
- 'copyright' => 'default',
- 'sourceavail' => 'closed',
- );
- $css_class = $itemcount%2?' class="LC_odd_row"':'';
- my %currrights;
- foreach my $item ('copyright','sourceavail') {
- $currrights{$item} = $staticdefaults{$item};
- if (ref($settings) eq 'HASH') {
- if (exists($settings->{$item})) {
- $currrights{$item} = $settings->{$item};
- }
- }
- }
- $datatable .= ''.
- ''.$titles{'copyright'}.
- ' '.
- &selectbox('copyright',$currrights{'copyright'},'',
- \&Apache::loncommon::copyrightdescription,
- (grep !/^priv|custom$/,(&Apache::loncommon::copyrightids))).
- ' '."\n";
- $itemcount ++;
- $css_class = $itemcount%2?' class="LC_odd_row"':'';
- $datatable .= ''.
- ''.$titles{'sourceavail'}.
- ' '.
- &selectbox('sourceavail',$currrights{'sourceavail'},'',
- \&Apache::loncommon::source_copyrightdescription,
- (&Apache::loncommon::source_copyrightids)).
- ' '."\n";
- } else {
- $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
- my $curreditors;
- my %staticdefaults = (
- editors => ['edit','xml'],
- authorquota => 500,
- webdav => 0,
- );
- my $curreditors = $staticdefaults{'editors'};
- if ((ref($settings) eq 'HASH') &&
- (ref($settings->{'editors'}) eq 'ARRAY')) {
- $curreditors = $settings->{'editors'};
- } else {
- $curreditors = $staticdefaults{'editors'};
- }
- my @editors = ('edit','xml','daxe');
- $datatable = ''."\n".
- ''.$titles{'editors'}.' '."\n".
- ''."\n".
- '';
- foreach my $editor (@editors) {
- my $checked;
- if (grep(/^\Q$editor\E$/,@{$curreditors})) {
- $checked = ' checked="checked"';
- }
- $datatable .= ''.
- ' '.
- $titles{$editor}.' ';
- }
- $datatable .= ' '."\n".' '."\n".' '."\n";
- $itemcount ++;
- $css_class = $itemcount%2?' class="LC_odd_row"':'';
- my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
- my @insttypes;
- if (ref($types) eq 'ARRAY') {
- @insttypes = @{$types};
- }
- my $typecount = 0;
- my %domconf = &Apache::lonnet::get_dom('configuration',['quotas'],$dom);
- my @items = ('webdav','authorquota');
- my %quotas;
- if (ref($domconf{'quotas'}) eq 'HASH') {
- %quotas = %{$domconf{'quotas'}};
- foreach my $item (@items) {
- if (ref($quotas{$item}) eq 'HASH') {
- foreach my $type (@insttypes,'default') {
- if ($item eq 'authorquota') {
- if ($quotas{$item}{$type} !~ /^\d+$/) {
- $quotas{$item}{$type} = $staticdefaults{$item};
- }
- } elsif ($item eq 'webdav') {
- if ($quotas{$item}{$type} !~ /^(0|1)$/) {
- $quotas{$item}{$type} = $staticdefaults{$item};
- }
- }
- }
- } else {
- foreach my $type (@insttypes,'default') {
- $quotas{$item}{$type} = $staticdefaults{$item};
- }
- }
- }
- } else {
- foreach my $item (@items) {
- foreach my $type (@insttypes,'default') {
- $quotas{$item}{$type} = $staticdefaults{$item};
- }
- }
- }
- if (ref($usertypes) eq 'HASH') {
- my $numinrow = 4;
- my $onclick = '';
- $datatable .= &insttypes_row(\%quotas,$types,$usertypes,$dom,
- $numinrow,$othertitle,'authorquota',
- \$itemcount,$onclick);
- $itemcount ++;
- $datatable .= &insttypes_row(\%quotas,$types,$usertypes,$dom,
- $numinrow,$othertitle,'webdav',
- \$itemcount);
- $itemcount ++;
- }
- my $checkedno = ' checked="checked"';
- my ($checkedon,$checkedoff);
- if (ref($quotas{'webdav'}) eq 'HASH') {
- if ($quotas{'webdav'}{'_LC_adv'} =~ /^0|1$/) {
- if ($quotas{'webdav'}{'_LC_adv'}) {
- $checkedon = $checkedno;
- } else {
- $checkedoff = $checkedno;
- }
- undef($checkedno);
- }
- }
- $css_class = $itemcount%2?' class="LC_odd_row"':'';
- $datatable .= ''.
- ''.$titles{'webdav_LC_adv'}.' '.
- $titles{'webdav_LC_adv_over'}.
- ' '.
- '';
- foreach my $option ('none','off','on') {
- my ($text,$val,$checked);
- if ($option eq 'none') {
- $text = $titles{'none'};
- $val = '';
- $checked = $checkedno;
- } elsif ($option eq 'off') {
- $text = $titles{'overoff'};
- $val = 0;
- $checked = $checkedoff;
- } elsif ($option eq 'on') {
- $text = $titles{'overon'};
- $val = 1;
- $checked = $checkedon;
- }
- $datatable .= ''.
- ' '.
- $text.' ';
- }
- $datatable .= ' ';
- $itemcount ++;
- my %defchecked = (
- 'archive' => 'off',
- );
- my @toggles = ('archive');
- (my $archive,$itemcount) = &radiobutton_prefs($settings,['archive'],
- {'archive' => 'off'},
- \%titles,$itemcount);
- $datatable .= $archive."\n";
$itemcount ++;
}
$$rowtotal += $itemcount;
return $datatable;
}
-sub authordefaults_titles {
- return &Apache::lonlocal::texthash(
- copyright => 'Copyright/Distribution',
- sourceavail => ' Source Available',
- editors => 'Available Editors',
- webdav => 'WebDAV',
- authorquota => 'Authoring Space quotas (MB)',
- nocodemirror => 'Deactivate CodeMirror for EditXML editor',
- daxecollapse => 'Daxe editor: LON-CAPA standard menus start collapsed',
- domcoordacc => 'Dom. Coords. can enter Authoring Spaces in domain',
- edit => 'Standard editor (Edit)',
- xml => 'Text editor (EditXML)',
- daxe => 'Daxe editor (Daxe)',
- webdav_LC_adv => 'WebDAV access for LON-CAPA "advanced" users',
- webdav_LC_adv_over => '(overrides access based on affiliation, if set)',
- none => 'No override set',
- overon => 'Override -- webDAV on',
- overoff => 'Override -- webDAV off',
- archive => 'Authors can download tar.gz file of Authoring Space',
- );
-}
-
-sub selectbox {
- my ($name,$value,$readonly,$functionref,@idlist)=@_;
- my $selout = '';
- foreach my $id (@idlist) {
- $selout.=''.&{$functionref}($id).' ';
- }
- $selout.=' ';
- return $selout;
-}
-
sub print_selfenrollment {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable);
my $itemcount = 1;
- my @types = ('official','unofficial','community','textbook');
+ my @types = ('official','unofficial','community','textbook','placement');
if (($position eq 'top') || ($position eq 'middle')) {
my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles();
my %descs = &Apache::lonuserutils::selfenroll_default_descs();
@@ -6893,6 +7707,143 @@ sub print_validation_rows {
return $datatable;
}
+sub print_privacy {
+ my ($position,$dom,$settings,$rowtotal) = @_;
+ my ($datatable,$css_class,$numinrow,@items,%names,$othertitle,$usertypes,$types);
+ my $itemcount = 0;
+ unless ($position eq 'top') {
+ @items = ('domain','author','course','community');
+ %names = &Apache::lonlocal::texthash (
+ domain => 'Assigned domain role(s)',
+ author => 'Assigned co-author role(s)',
+ course => 'Assigned course role(s)',
+ community => 'Assigned community role',
+ );
+ $numinrow = 4;
+ ($othertitle,$usertypes,$types) =
+ &Apache::loncommon::sorted_inst_types($dom);
+ }
+ if (($position eq 'top') || ($position eq 'middle')) {
+ my (%by_ip,%by_location,@intdoms,@instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+ if ($position eq 'top') {
+ my %curr;
+ my @options = ('none','user','domain','auto');
+ my %titles = &Apache::lonlocal::texthash (
+ none => 'Not allowed',
+ user => 'User authorizes',
+ domain => 'DC authorizes',
+ auto => 'Unrestricted',
+ instdom => 'Other domain shares institution/provider',
+ extdom => 'Other domain has different institution/provider',
+ );
+ my %names = &Apache::lonlocal::texthash (
+ domain => 'Domain role',
+ author => 'Co-author role',
+ course => 'Course role',
+ community => 'Community role',
+ );
+ my $primary_id = &Apache::lonnet::domain($dom,'primary');
+ my $intdom = &Apache::lonnet::internet_dom($primary_id);
+ foreach my $domtype ('instdom','extdom') {
+ my (%checked,$skip);
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{$domtype}.' '.
+ '';
+ if ($domtype eq 'instdom') {
+ unless (@instdoms > 1) {
+ $datatable .= &mt('Nothing to set, as no domains besides [_1] are hosted by [_2]',$dom,$intdom);
+ $skip = 1;
+ }
+ } elsif ($domtype eq 'extdom') {
+ if (keys(%by_location) == 0) {
+ $datatable .= &mt('Nothing to set, as no other hosts besides [_1]',$intdom);
+ $skip = 1;
+ }
+ }
+ unless ($skip) {
+ foreach my $roletype ('domain','author','course','community') {
+ $checked{'auto'} = ' checked="checked"';
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{approval}) eq 'HASH') {
+ if (ref($settings->{approval}->{$domtype}) eq 'HASH') {
+ if ($settings->{approval}->{$domtype}->{$roletype}=~ /^(none|user|domain)$/) {
+ $checked{$1} = ' checked="checked"';
+ $checked{'auto'} = '';
+ }
+ }
+ }
+ }
+ $datatable .= ''.$names{$roletype}.' ';
+ foreach my $option (@options) {
+ $datatable .= ''.
+ ' '.$titles{$option}.
+ ' ';
+ }
+ $datatable .= ' ';
+ }
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ }
+ } elsif ($position eq 'middle') {
+ if ((@instdoms > 1) || (keys(%by_location) > 0)) {
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $item (@{$types}) {
+ $datatable .= &modifiable_userdata_row('privacy','othdom_'.$item,$settings,
+ $numinrow,$itemcount,'','','','','',
+ '',$usertypes->{$item});
+ $itemcount ++;
+ }
+ }
+ $datatable .= &modifiable_userdata_row('privacy','othdom_default',$settings,
+ $numinrow,$itemcount,'','','','','',
+ '',$othertitle);
+ $itemcount ++;
+ } else {
+ my (@insttypes,%insttitles);
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ @insttypes = @{$types};
+ %insttitles = %{$usertypes};
+ }
+ foreach my $item (@insttypes,'default') {
+ my $title;
+ if ($item eq 'default') {
+ $title = $othertitle;
+ } else {
+ $title = $insttitles{$item};
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.
+ ''.$title.' '.
+ ''.
+ &mt('Nothing to set here, as there are no other domains').
+ ' ';
+ $itemcount ++;
+ }
+ }
+ }
+ } else {
+ my $prefix;
+ if ($position eq 'lower') {
+ $prefix = 'priv';
+ } else {
+ $prefix = 'unpriv';
+ }
+ foreach my $item (@items) {
+ $datatable .= &modifiable_userdata_row('privacy',$prefix.'_'.$item,$settings,
+ $numinrow,$itemcount,'','','','','',
+ '',$names{$item});
+ $itemcount ++;
+ }
+ }
+ if (ref($rowtotal)) {
+ $$rowtotal += $itemcount;
+ }
+ return $datatable;
+}
+
sub print_passwords {
my ($position,$dom,$confname,$settings,$rowtotal) = @_;
my ($datatable,$css_class);
@@ -6914,6 +7865,7 @@ sub print_passwords {
min => 'Minimum password length',
max => 'Maximum password length',
chars => 'Required characters',
+ expire => 'Password expiration (days)',
numsaved => 'Number of previous passwords to save and disallow reuse',
);
if ($position eq 'top') {
@@ -7203,7 +8155,7 @@ sub print_passwords {
$datatable .= ''.
''.
&mt('Requirements').''.
- ''.&mt("Course 'type' is not a Community").' '.
+ ''.&mt("Course 'type' is not a Community or Placement Test").' '.
''.&mt('User is Course Coordinator and also course owner').' '.
''.&mt("Student's only active roles are student role(s) in course(s) owned by this user").' '.
''.&mt('User, course, and student share same domain').' '.
@@ -7240,7 +8192,7 @@ sub print_passwords {
sub password_rules {
my ($prefix,$itemcountref,$settings) = @_;
- my ($min,$max,%chars,$numsaved,$numinrow);
+ my ($min,$max,%chars,$expire,$numsaved,$numinrow);
my %titles;
if ($prefix eq 'passwords') {
%titles = &Apache::lonlocal::texthash (
@@ -7248,7 +8200,7 @@ sub password_rules {
max => 'Maximum password length',
chars => 'Required characters',
);
- } elsif (($prefix eq 'ltisecrets') || ($prefix eq 'toolsecrets')) {
+ } elsif ($prefix eq 'secrets') {
%titles = &Apache::lonlocal::texthash (
min => 'Minimum secret length',
max => 'Maximum secret length',
@@ -7271,7 +8223,10 @@ sub password_rules {
if (ref($settings->{chars}) eq 'ARRAY') {
map { $chars{$_} = 1; } (@{$settings->{chars}});
}
- if ($prefix eq 'passwords') {
+ if ($prefix eq 'passwords') {
+ if ($settings->{expire}) {
+ $expire = $settings->{expire};
+ }
if ($settings->{numsaved}) {
$numsaved = $settings->{numsaved};
}
@@ -7333,8 +8288,17 @@ sub password_rules {
$datatable .='
';
$itemcount ++;
if ($prefix eq 'passwords') {
+ $titles{'expire'} = &mt('Password expiration (days)');
$titles{'numsaved'} = &mt('Number of previous passwords to save and disallow reuse');
$css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'expire'}.' '.
+ ''.
+ ' '.
+ ' '.&mt('(Leave blank for no expiration)').' '.
+ ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
$datatable .= ''.$titles{'numsaved'}.' '.
''.
' '.
' '.
- &mt('Hostname').': '.
- ''.
- &Apache::lonnet::hostname($server).' ';
+ &mt('Hostname').': '.
+ ''.&Apache::lonnet::hostname($server).' ';
if ($othercontrol{$server}) {
$dom_in_effect = $othercontrol{$server};
my ($current,$forsaml);
@@ -7468,10 +8431,10 @@ sub print_wafproxy {
(' 'x2).''.
&mt('Alias used for SSO Auth').': '.
' '.
- &mt('No').' '.
+ &mt('No').' '.
' '.
&mt('Yes').' '.
- '';
+ '';
}
$aliasrows .= ' ';
$aliasinfo{$dom_in_effect} .= $aliasrows;
@@ -7659,15 +8622,14 @@ sub remoteip_methods {
sub print_usersessions {
my ($position,$dom,$settings,$rowtotal) = @_;
- my ($css_class,$datatable,%checked,%choices);
- my (%by_ip,%by_location,@intdoms);
- &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
+ my ($css_class,$datatable,$itemcount,%checked,%choices);
+ my (%by_ip,%by_location,@intdoms,@instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
my @alldoms = &Apache::lonnet::all_domains();
my %serverhomes = %Apache::lonnet::serverhomeIDs;
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %altids = &id_for_thisdom(%servers);
- my $itemcount = 1;
if ($position eq 'top') {
if (keys(%serverhomes) > 1) {
my %spareid = ¤t_offloads_to($dom,$settings,\%servers);
@@ -7689,116 +8651,252 @@ sub print_usersessions {
'';
}
} else {
- if (keys(%by_location) == 0) {
- $datatable .= ''.
- &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
- ' ';
+ my %titles = &usersession_titles();
+ my ($prefix,@types);
+ if ($position eq 'bottom') {
+ $prefix = 'remote';
+ @types = ('version','excludedomain','includedomain');
} else {
- my %lt = &usersession_titles();
- my $numinrow = 5;
- my $prefix;
- my @types;
- if ($position eq 'bottom') {
- $prefix = 'remote';
- @types = ('version','excludedomain','includedomain');
- } else {
- $prefix = 'hosted';
- @types = ('excludedomain','includedomain');
- }
- my (%current,%checkedon,%checkedoff);
- my @lcversions = &Apache::lonnet::all_loncaparevs();
- my @locations = sort(keys(%by_location));
- foreach my $type (@types) {
- $checkedon{$type} = '';
- $checkedoff{$type} = ' checked="checked"';
- }
- if (ref($settings) eq 'HASH') {
- if (ref($settings->{$prefix}) eq 'HASH') {
- foreach my $key (keys(%{$settings->{$prefix}})) {
- $current{$key} = $settings->{$prefix}{$key};
- if ($key eq 'version') {
- if ($current{$key} ne '') {
- $checkedon{$key} = ' checked="checked"';
- $checkedoff{$key} = '';
- }
- } elsif (ref($current{$key}) eq 'ARRAY') {
+ $prefix = 'hosted';
+ @types = ('excludedomain','includedomain');
+ }
+ ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
+ }
+ $$rowtotal += $itemcount;
+ return $datatable;
+}
+
+sub rules_by_location {
+ my ($settings,$prefix,$by_location,$by_ip,$types,$titles) = @_;
+ my ($datatable,$itemcount,$css_class);
+ if (keys(%{$by_location}) == 0) {
+ $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
+ $datatable = ''.
+ &mt('Nothing to set here, as the cluster to which this domain belongs only contains one institution.').
+ ' ';
+ $itemcount = 1;
+ } else {
+ $itemcount = 0;
+ my $numinrow = 5;
+ my (%current,%checkedon,%checkedoff);
+ my @locations = sort(keys(%{$by_location}));
+ foreach my $type (@{$types}) {
+ $checkedon{$type} = '';
+ $checkedoff{$type} = ' checked="checked"';
+ }
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{$prefix}) eq 'HASH') {
+ foreach my $key (keys(%{$settings->{$prefix}})) {
+ $current{$key} = $settings->{$prefix}{$key};
+ if ($key eq 'version') {
+ if ($current{$key} ne '') {
$checkedon{$key} = ' checked="checked"';
$checkedoff{$key} = '';
}
+ } elsif (ref($current{$key}) eq 'ARRAY') {
+ $checkedon{$key} = ' checked="checked"';
+ $checkedoff{$key} = '';
}
}
}
- foreach my $type (@types) {
- next if ($type ne 'version' && !@locations);
- $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
- $datatable .= '
- '.$lt{$type}.'
-
- '.&mt('Not in use').'
- '.&mt('In use').' ';
- if ($type eq 'version') {
- my $selector = '';
- foreach my $version (@lcversions) {
- my $selected = '';
- if ($current{'version'} eq $version) {
- $selected = ' selected="selected"';
- }
- $selector .= ' '.$version.' ';
+ }
+ foreach my $type (@{$types}) {
+ next if ($type ne 'version' && !@locations);
+ $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
+ $datatable .= '
+ '.$titles->{$type}.'
+
+ '.&mt('Not in use').'
+ '.&mt('In use').' ';
+ if ($type eq 'version') {
+ my @lcversions = &Apache::lonnet::all_loncaparevs();
+ my $selector = '';
+ foreach my $version (@lcversions) {
+ my $selected = '';
+ if ($current{'version'} eq $version) {
+ $selected = ' selected="selected"';
}
- $selector .= ' ';
- $datatable .= &mt('remote server must be version: [_1] or later',$selector);
- } else {
- $datatable.= ' '.(' 'x2).
- ' '.
- "\n".
- '
';
- my $rem;
- for (my $i=0; $i<@locations; $i++) {
- my ($showloc,$value,$checkedtype);
- if (ref($by_location{$locations[$i]}) eq 'ARRAY') {
- my $ip = $by_location{$locations[$i]}->[0];
- if (ref($by_ip{$ip}) eq 'ARRAY') {
- $value = join(':',@{$by_ip{$ip}});
- $showloc = join(', ',@{$by_ip{$ip}});
- if (ref($current{$type}) eq 'ARRAY') {
- foreach my $loc (@{$by_ip{$ip}}) {
- if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
- $checkedtype = ' checked="checked"';
- last;
- }
+ $selector .= ' '.$version.' ';
+ }
+ $selector .= ' ';
+ $datatable .= &mt('remote server must be version: [_1] or later',$selector);
+ } else {
+ $datatable.= ' '.(' 'x2).
+ ' '.
+ "\n".
+ '
';
+ }
+ $datatable .= '';
+ $itemcount ++;
+ }
+ }
+ return ($datatable,$itemcount);
+}
+
+sub print_ssl {
+ my ($position,$dom,$settings,$rowtotal) = @_;
+ my ($css_class,$datatable);
+ my $itemcount = 1;
+ if ($position eq 'top') {
+ my $primary_id = &Apache::lonnet::domain($dom,'primary');
+ my $intdom = &Apache::lonnet::internet_dom($primary_id);
+ my $same_institution;
+ if ($intdom ne '') {
+ my $internet_names = &Apache::lonnet::get_internet_names($Apache::lonnet::perlvar{'lonHostID'});
+ if (ref($internet_names) eq 'ARRAY') {
+ if (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+ $same_institution = 1;
+ }
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable = '
';
+ if ($same_institution) {
+ my %domservers = &Apache::lonnet::get_servers($dom);
+ $datatable .= &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs');
+ } else {
+ $datatable .= &mt("You need to be logged into one of your own domain's servers to display information about the status of LON-CAPA SSL certificates.");
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ } else {
+ my %titles = &ssl_titles();
+ my (%by_ip,%by_location,@intdoms,@instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+ my @alldoms = &Apache::lonnet::all_domains();
+ my %serverhomes = %Apache::lonnet::serverhomeIDs;
+ my @domservers = &Apache::lonnet::get_servers($dom);
+ my %servers = &Apache::lonnet::internet_dom_servers($dom);
+ my %altids = &id_for_thisdom(%servers);
+ if (($position eq 'connto') || ($position eq 'connfrom')) {
+ my $legacy;
+ unless (ref($settings) eq 'HASH') {
+ my $name;
+ if ($position eq 'connto') {
+ $name = 'loncAllowInsecure';
+ } else {
+ $name = 'londAllowInsecure';
+ }
+ my $primarylibserv = &Apache::lonnet::domain($dom,'primary');
+ my @ids=&Apache::lonnet::current_machine_ids();
+ if (($primarylibserv ne '') && (!grep(/^\Q$primarylibserv\E$/,@ids))) {
+ my %what = (
+ $name => 1,
+ );
+ my ($result,$returnhash) =
+ &Apache::lonnet::get_remote_globals($primarylibserv,\%what);
+ if ($result eq 'ok') {
+ if (ref($returnhash) eq 'HASH') {
+ $legacy = $returnhash->{$name};
+ }
+ }
+ } else {
+ $legacy = $Apache::lonnet::perlvar{$name};
+ }
+ }
+ foreach my $type ('dom','intdom','other') {
+ my %checked;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '
'.$titles{$type}.' '.
+ '';
+ my $skip;
+ if ($type eq 'dom') {
+ unless (keys(%servers) > 1) {
+ $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');
+ $skip = 1;
+ }
+ }
+ if ($type eq 'intdom') {
+ unless (@instdoms > 1) {
+ $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
+ $skip = 1;
+ }
+ } elsif ($type eq 'other') {
+ if (keys(%by_location) == 0) {
+ $datatable .= &mt('Nothing to set here, as there are no other institutions');
+ $skip = 1;
+ }
+ }
+ unless ($skip) {
+ $checked{'yes'} = ' checked="checked"';
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{$position}) eq 'HASH') {
+ if ($settings->{$position}->{$type} =~ /^(no|req)$/) {
+ $checked{$1} = $checked{'yes'};
+ delete($checked{'yes'});
+ }
+ }
+ } else {
+ if ($legacy == 0) {
+ $checked{'req'} = $checked{'yes'};
+ delete($checked{'yes'});
+ }
+ }
+ foreach my $option ('no','yes','req') {
+ $datatable .= ''.
+ ' '.$titles{$option}.
+ ' '.(' 'x2);
}
- $datatable .= '
';
}
$datatable .= '
';
+ $itemcount ++;
+ }
+ } else {
+ my $prefix = 'replication';
+ my @types = ('certreq','nocertreq');
+ if (keys(%by_location) == 0) {
+ $datatable .= ''.
+ &mt('Nothing to set here, as there are no other institutions').
+ ' ';
$itemcount ++;
+ } else {
+ ($datatable,$itemcount) =
+ &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
}
}
}
@@ -7806,10 +8904,60 @@ sub print_usersessions {
return $datatable;
}
+sub ssl_titles {
+ return &Apache::lonlocal::texthash (
+ dom => 'LON-CAPA servers/VMs from same domain',
+ intdom => 'LON-CAPA servers/VMs from same "internet" domain',
+ other => 'External LON-CAPA servers/VMs',
+ connto => 'Connections to other servers',
+ connfrom => 'Connections from other servers',
+ replication => 'Replicating content to other institutions',
+ certreq => 'Client certificate required, but specific domains exempt',
+ nocertreq => 'No client certificate required, except for specific domains',
+ no => 'SSL not used',
+ yes => 'SSL Optional (used if available)',
+ req => 'SSL Required',
+ );
+}
+
+sub print_trust {
+ my ($prefix,$dom,$settings,$rowtotal) = @_;
+ my ($css_class,$datatable,%checked,%choices);
+ my (%by_ip,%by_location,@intdoms,@instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+ my $itemcount = 1;
+ my %titles = &trust_titles();
+ my @types = ('exc','inc');
+ if ($prefix eq 'top') {
+ $prefix = 'content';
+ } elsif ($prefix eq 'bottom') {
+ $prefix = 'msg';
+ }
+ ($datatable,$itemcount) = &rules_by_location($settings,$prefix,\%by_location,\%by_ip,\@types,\%titles);
+ $$rowtotal += $itemcount;
+ return $datatable;
+}
+
+sub trust_titles {
+ return &Apache::lonlocal::texthash(
+ content => "Access to this domain's content by others",
+ shared => "Access to other domain's content by this domain",
+ enroll => "Enrollment in this domain's courses by others",
+ othcoau => "Co-author roles in this domain for others",
+ coaurem => "Co-author roles for this domain's users elsewhere",
+ domroles => "Domain roles in this domain assignable to others",
+ catalog => "Course Catalog for this domain displayed elsewhere",
+ reqcrs => "Requests for creation of courses in this domain by others",
+ msg => "Users in other domains can send messages to this domain",
+ exc => "Allow all, but exclude specific domains",
+ inc => "Deny all, but include specific domains",
+ );
+}
+
sub build_location_hashes {
- my ($intdoms,$by_ip,$by_location) = @_;
+ my ($intdoms,$by_ip,$by_location,$instdoms) = @_;
return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
- (ref($by_location) eq 'HASH'));
+ (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY'));
my %iphost = &Apache::lonnet::get_iphost();
my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
@@ -7826,7 +8974,13 @@ sub build_location_hashes {
foreach my $id (@{$iphost{$ip}}) {
my $location = &Apache::lonnet::internet_dom($id);
if ($location) {
- next if (grep(/^\Q$location\E$/,@{$intdoms}));
+ if (grep(/^\Q$location\E$/,@{$intdoms})) {
+ my $dom = &Apache::lonnet::host_domain($id);
+ unless (grep(/^\Q$dom\E/,@{$instdoms})) {
+ push(@{$instdoms},$dom);
+ }
+ next;
+ }
if (ref($by_ip->{$ip}) eq 'ARRAY') {
unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
push(@{$by_ip->{$ip}},$location);
@@ -8146,7 +9300,7 @@ sub print_loadbalancing {
my $disabled_div_style = 'display: block';
my $homedom_div_style = 'display: none';
$datatable .= ''.
- ''.
+ ' '.
'';
if ($lonhost eq '') {
$datatable .= '';
@@ -8179,7 +9333,7 @@ sub print_loadbalancing {
$homedom_div_style = 'display: block';
}
}
- $datatable .= '
'.
+ $datatable .= ' '.
''.$disabledtext.'
'."\n".
''.&mt('Offloads to:').'
';
@@ -8190,7 +9344,7 @@ sub print_loadbalancing {
no => ' checked="checked"',
);
my %balcookiechecked = (
- no => ' checked="checked"',
+ no => ' checked="checked"',
);
foreach my $sparetype (@sparestypes) {
my $targettable;
@@ -8411,7 +9565,7 @@ sub loadbalance_rule_row {
$space = '
';
}
my $output =
- '
'.$space.
+ ' '.$space.
''.$title.'
'."\n".
''.$space.
''."\n";
@@ -8545,13 +9699,13 @@ sub tool_titles {
my %titles = &Apache::lonlocal::texthash (
aboutme => 'Personal web page',
blog => 'Blog',
+ webdav => 'WebDAV',
portfolio => 'Portfolio',
- portaccess => 'Share portfolio files',
- timezone => 'Can set time zone',
official => 'Official courses (with institutional codes)',
unofficial => 'Unofficial courses',
community => 'Communities',
textbook => 'Textbook courses',
+ placement => 'Placement tests',
);
return %titles;
}
@@ -8562,9 +9716,10 @@ sub courserequest_titles {
unofficial => 'Unofficial',
community => 'Communities',
textbook => 'Textbook',
+ placement => 'Placement tests',
lti => 'LTI Provider',
norequest => 'Not allowed',
- approval => 'Approval by Dom. Coord.',
+ approval => 'Approval by DC',
validate => 'With validation',
autolimit => 'Numerical limit',
unlimited => '(blank for unlimited)',
@@ -8653,7 +9808,7 @@ sub print_usercreation {
}
$datatable .= '
'.
''.$lt{$item}.
- ' ';
+ ' ';
my @options = ('any');
if (ref($rules) eq 'HASH') {
if (keys(%{$rules}) > 0) {
@@ -8775,7 +9930,7 @@ sub print_selfcreation {
($datatable,$itemcount) = &radiobutton_prefs(\%radiohash,\@toggles,\%defaultchecked,
\%choices,$itemcount,$onclick);
$$rowtotal += $itemcount;
-
+
if (ref($usertypes) eq 'HASH') {
if (keys(%{$usertypes}) > 0) {
$datatable .= &insttypes_row($createsettings,$types,$usertypes,
@@ -8912,7 +10067,7 @@ sub print_selfcreation {
my $currstyle = 'display:none';
if (grep(/^\Q$status\E$/,@ordered)) {
$currstyle = $rowstyle;
- $hidden = 0;
+ $hidden = 0;
}
$datatable .= &noninst_users($processing,$emailverified,$emailoptions,$emaildomain,
$emailrules,$emailruleorder,$settings,$status,$rowid,
@@ -8939,8 +10094,8 @@ sub print_selfcreation {
foreach my $status (@posstypes) {
my $rowid = $classprefix.$status;
my $datarowstyle = 'display:none';
- if (grep(/^\Q$status\E$/,@ordered)) {
- $datarowstyle = $rowstyle;
+ if (grep(/^\Q$status\E$/,@ordered)) {
+ $datarowstyle = $rowstyle;
}
$datatable .= &modifiable_userdata_row('cancreate','emailusername_'.$status,$settings,
$numinrow,$$rowtotal,\%usertypeshash,$infofields,
@@ -9042,7 +10197,7 @@ function toggleEmailOptions(form,radio,p
document.getElementById(altprefix+'_inst_'+status).style.display = 'none';
document.getElementById(altprefix+'_noninst_'+status).style.display = 'none';
if (curr == 'custom') {
- if (prefix) {
+ if (prefix) {
document.getElementById(prefix+'_'+status).style.display = 'inline';
}
} else if (curr == 'inst') {
@@ -9065,10 +10220,10 @@ ENDSCRIPT
sub noninst_users {
my ($processing,$emailverified,$emailoptions,$emaildomain,$emailrules,
- $emailruleorder,$settings,$type,$rowid,$typetitle,$css_class,$rowstyle,$intdom) = @_;
+ $emailruleorder,$settings,$type,$rowid,$typetitle,$css_class,$rowstyle,$intdom) = @_;
my $class = 'LC_left_item';
if ($css_class) {
- $css_class = ' class="'.$css_class.'"';
+ $css_class = ' class="'.$css_class.'"';
}
if ($rowid) {
$rowid = ' id="'.$rowid.'"';
@@ -9083,10 +10238,10 @@ sub noninst_users {
$description = &mt('Requests for: [_1] (status self-reported)',$typetitle);
}
$output = ' '.
- "$description \n".
+ "$description \n".
''.
'';
- my %headers = &Apache::lonlocal::texthash(
+ my %headers = &Apache::lonlocal::texthash(
approve => 'Processing',
email => 'E-mail',
username => 'Username',
@@ -9096,7 +10251,7 @@ sub noninst_users {
}
$output .= ' ';
foreach my $item ('approve','email','username') {
- $output .= '';
+ $output .= ' ';
my (%choices,@options,$hashref,$defoption,$name,$onclick,$hascustom);
if ($item eq 'approve') {
%choices = &Apache::lonlocal::texthash (
@@ -9211,7 +10366,7 @@ sub noninst_users {
my $value;
if (ref($emaildomain) eq 'HASH') {
if (ref($emaildomain->{$type}) eq 'HASH') {
- $value = $emaildomain->{$type}->{$option};
+ $value = $emaildomain->{$type}->{$option};
}
}
if ($value eq '') {
@@ -9516,29 +10671,13 @@ sub print_defaults {
} elsif ($item eq 'lang_def') {
my $includeempty = 1;
$datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);
- } elsif ($item eq 'portal_def') {
- $datatable .= ' ';
- my $portalsty = 'none';
- if ($defaults{$item}) {
- $portalsty = 'block';
- }
- foreach my $field ('email','web') {
- my $checkedoff = ' checked="checked"';
- my $checkedon;
- if ($defaults{$item.'_'.$field}) {
- $checkedon = $checkedoff;
- $checkedoff = '';
- }
- $datatable .= ''.
- ''.$titles->{$field}.' '.
- ' '.&mt('Yes').' '.
- (' 'x2).
- ' '.&mt('No').' '.
- '
';
- }
} else {
- $datatable .= ' ';
+ my $size;
+ if ($item eq 'portal_def') {
+ $size = ' size="25"';
+ }
+ $datatable .= ' ';
}
$datatable .= ' ';
$rownum ++;
@@ -9567,7 +10706,7 @@ sub print_defaults {
$datatable .= ' '.&mt('Internal ID:').' '.$item.' '.
' '.
&mt('delete').''.
- ''.&mt('Name displayed').':'.
+ ' '.&mt('Name displayed').':'.
' '.
' ';
}
@@ -9586,7 +10725,7 @@ sub print_defaults {
$datatable .= ' '.&mt('Internal ID:').
' '.
' '.&mt('(new)').
- ''.
+ ' '.
&mt('Name displayed').':'.
' '.
''."\n";
@@ -9634,8 +10773,6 @@ sub defaults_titles {
'timezone_def' => 'Default timezone',
'datelocale_def' => 'Default locale for dates',
'portal_def' => 'Portal/Default URL',
- 'email' => 'Email links use portal URL',
- 'web' => 'Public web links use portal URL',
'intauth_cost' => 'Encryption cost for bcrypt (positive integer)',
'intauth_check' => 'Check bcrypt cost if authenticated',
'intauth_switch' => 'Existing crypt-based switched to bcrypt on authentication',
@@ -9821,7 +10958,7 @@ sub print_scantronformat {
}
$datatable .= '';
if (keys(%error) == 0) {
- $datatable .= '';
+ $datatable .= ' ';
if (!$switchserver) {
$datatable .= &mt('Upload:').' ';
}
@@ -9868,13 +11005,10 @@ sub legacy_scantronformat {
my ($url,$error);
my @statinfo = &Apache::lonnet::stat_file($newurl);
if ((!@statinfo) || ($statinfo[0] eq 'no_such_dir')) {
- my $modified = [];
(my $result,$url) =
- &Apache::lonconfigsettings::publishlogo($r,'copy',$legacyfile,$dom,$confname,
- 'scantron','','',$newfile,$modified);
- if ($result eq 'ok') {
- &update_modify_urls($r,$modified);
- } else {
+ &publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron',
+ '','',$newfile);
+ if ($result ne 'ok') {
$error = &mt("An error occurred publishing the [_1] bubblesheet format file in RES space. Error was: [_2].",$newfile,$result);
}
}
@@ -10059,6 +11193,10 @@ sub print_coursecategories {
my $toggle_catscomm_dom = ' checked="checked" ';
my $can_catcomm_comm = ' ';
my $can_catcomm_dom = ' checked="checked" ';
+ my $toggle_catsplace_place = ' ';
+ my $toggle_catsplace_dom = ' checked="checked" ';
+ my $can_catplace_place = ' ';
+ my $can_catplace_dom = ' checked="checked" ';
if (ref($settings) eq 'HASH') {
if ($settings->{'togglecats'} eq 'crs') {
@@ -10077,17 +11215,28 @@ sub print_coursecategories {
$can_catcomm_comm = $can_catcomm_dom;
$can_catcomm_dom = ' ';
}
+ if ($settings->{'togglecatsplace'} eq 'place') {
+ $toggle_catsplace_place = $toggle_catsplace_dom;
+ $toggle_catsplace_dom = ' ';
+ }
+ if ($settings->{'categorizeplace'} eq 'place') {
+ $can_catplace_place = $can_catplace_dom;
+ $can_catplace_dom = ' ';
+ }
}
my %title = &Apache::lonlocal::texthash (
- togglecats => 'Show/Hide a course in catalog',
- togglecatscomm => 'Show/Hide a community in catalog',
- categorize => 'Assign a category to a course',
- categorizecomm => 'Assign a category to a community',
+ togglecats => 'Show/Hide a course in catalog',
+ togglecatscomm => 'Show/Hide a community in catalog',
+ togglecatsplace => 'Show/Hide a placement test in catalog',
+ categorize => 'Assign a category to a course',
+ categorizecomm => 'Assign a category to a community',
+ categorizeplace => 'Assign a category to a placement test',
);
my %level = &Apache::lonlocal::texthash (
- dom => 'Set in Domain',
- crs => 'Set in Course',
- comm => 'Set in Community',
+ dom => 'Set in Domain',
+ crs => 'Set in Course',
+ comm => 'Set in Community',
+ place => 'Set in Placement Test',
);
$datatable = ' '.
''.$title{'togglecats'}.' '.
@@ -10117,8 +11266,22 @@ sub print_coursecategories {
$can_catcomm_dom.' value="dom" />'.$level{'dom'}.' '.
' '.$level{'comm'}.' '.
+ ' '.
+ ''.$title{'togglecatsplace'}.' '.
+ ''.
+ ' '.$level{'dom'}.' '.
+ ' '.$level{'place'}.' '.
+ ' '.
+ ''.$title{'categorizeplace'}.' '.
+ ''.
+ ' '.$level{'dom'}.' '.
+ ' '.$level{'place'}.' '.
' ';
- $$rowtotal += 4;
+ $$rowtotal += 6;
} else {
my $css_class;
my $itemcount = 1;
@@ -10143,12 +11306,15 @@ sub print_coursecategories {
my %default_names = (
instcode => &mt('Official courses'),
communities => &mt('Communities'),
+ placement => &mt('Placement Tests'),
);
if ((!grep(/^instcode$/,@{$cats[0]})) ||
($cathash->{'instcode::0'} eq '') ||
(!grep(/^communities$/,@{$cats[0]})) ||
- ($cathash->{'communities::0'} eq '')) {
+ ($cathash->{'communities::0'} eq '') ||
+ (!grep(/^placement$/,@{$cats[0]})) ||
+ ($cathash->{'placement::0'} eq '')) {
$maxnum ++;
}
my $lastidx;
@@ -10169,7 +11335,7 @@ sub print_coursecategories {
$datatable .= ''.$vpos.' ';
}
$datatable .= '';
- if ($parent eq 'instcode' || $parent eq 'communities') {
+ if ($parent eq 'instcode' || $parent eq 'communities' || $parent eq 'placement') {
$datatable .= ''
.$default_names{$parent}.' ';
if ($parent eq 'instcode') {
@@ -10192,7 +11358,7 @@ sub print_coursecategories {
$datatable .= ' '
.&mt('Do not display').' ';
- if ($parent eq 'communities') {
+ if (($parent eq 'communities') || ($parent eq 'placement')) {
$datatable .= '
';
}
$datatable .= ' ';
@@ -10224,7 +11390,7 @@ sub print_coursecategories {
.' '
.' '."\n";
$itemcount ++;
- foreach my $default ('instcode','communities') {
+ foreach my $default ('instcode','communities','placement') {
if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"';
@@ -10313,31 +11479,14 @@ sub print_serverstatuses {
sub serverstatus_pages {
return ('userstatus','lonstatus','loncron','server-status','codeversions',
- 'checksums','clusterstatus','metadata_keywords','metadata_harvest',
- 'takeoffline','takeonline','showenv','toggledebug','ping','domconf',
- 'uniquecodes','diskusage','coursecatalog');
+ 'checksums','clusterstatus','certstatus','metadata_keywords',
+ 'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
+ 'ping','domconf','uniquecodes','diskusage','coursecatalog');
}
sub defaults_javascript {
my ($settings) = @_;
return unless (ref($settings) eq 'HASH');
- my $portal_js = <<"ENDPORTAL";
-
-function portalExtras(caller) {
- var x = caller.value;
- var y = new Array('email','web');
- for (var i=0; i
0) {
- z.style.display = 'block';
- } else {
- z.style.display = 'none';
- }
- }
- }
-}
-ENDPORTAL
if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
my $maxnum = scalar(@{$settings->{'inststatusorder'}});
if ($maxnum eq '') {
@@ -10391,17 +11540,6 @@ $jstext
return;
}
-$portal_js
-
-// ]]>
-
-
-ENDSCRIPT
- } else {
-return <<"ENDSCRIPT";
-
@@ -10419,9 +11557,10 @@ sub passwords_javascript {
authcost => 'Warning: bcrypt encryption cost for internal authentication must be an integer.',
passmin => 'Warning: minimum password length must be a positive integer greater than 6.',
passmax => 'Warning: maximum password length must be a positive integer (or blank).',
+ passexp => 'Warning: days before password expiration must be a positive integer (or blank).',
passnum => 'Warning: number of previous passwords to save must be a positive integer (or blank).',
);
- } elsif (($prefix eq 'ltisecrets') || ($prefix eq 'toolsecrets')) {
+ } elsif ($prefix eq 'secrets') {
%intalert = &Apache::lonlocal::texthash (
passmin => 'Warning: minimum secret length must be a positive integer greater than 6.',
passmax => 'Warning: maximum secret length must be a positive integer (or blank).',
@@ -10429,7 +11568,7 @@ sub passwords_javascript {
}
&js_escape(\%intalert);
my $defmin = $Apache::lonnet::passwdmin;
- my $intauthjs;
+ my $intauthjs;
if ($prefix eq 'passwords') { $intauthjs = <<"ENDSCRIPT";
function warnIntAuth(field) {
@@ -10480,15 +11619,29 @@ function warnInt$prefix(field) {
field.value = '';
}
if (field.value != '') {
- if (!regexdigit.test(field.value)) {
- if (field.name == '${prefix}_max') {
- alert('$intalert{passmax}');
+ if (field.name == '${prefix}_expire') {
+ var regexpposnum=/^\\d+(|\\.\\d*)\$/;
+ if (!regexpposnum.test(field.value)) {
+ alert('$intalert{passexp}');
+ field.value = '';
} else {
- if (field.name == '${prefix}_numsaved') {
- alert('$intalert{passnum}');
+ var expval = parseFloat(field.value);
+ if (expval == 0) {
+ alert('$intalert{passexp}');
+ field.value = '';
}
}
- field.value = '';
+ } else {
+ if (!regexdigit.test(field.value)) {
+ if (field.name == '${prefix}_max') {
+ alert('$intalert{passmax}');
+ } else {
+ if (field.name == '${prefix}_numsaved') {
+ alert('$intalert{passnum}');
+ }
+ }
+ field.value = '';
+ }
}
}
}
@@ -10523,9 +11676,11 @@ sub coursecategories_javascript {
}
my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"');
my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"');
+ my $placement_reserved = &mt('The name: [_1] is a reserved category.','"placement"');
my $choose_again = "\n".&mt('Please use a different name for the new top level category.');
&js_escape(\$instcode_reserved);
&js_escape(\$communities_reserved);
+ &js_escape(\$placement_reserved);
&js_escape(\$choose_again);
$output = <<"ENDSCRIPT";