';
+ $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',
+ 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',
+ );
+}
+
+sub selectbox {
+ my ($name,$value,$readonly,$functionref,@idlist)=@_;
+ my $selout = '';
+ return $selout;
+}
+
sub print_selfenrollment {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable);
@@ -7714,7 +7638,9 @@ 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') {
+ if ($position eq 'top') {
+ $numinrow = 2;
+ } else {
@items = ('domain','author','course','community');
%names = &Apache::lonlocal::texthash (
domain => 'Assigned domain role(s)',
@@ -7739,6 +7665,7 @@ sub print_privacy {
auto => 'Unrestricted',
instdom => 'Other domain shares institution/provider',
extdom => 'Other domain has different institution/provider',
+ notify => 'Notify when role needs authorization',
);
my %names = &Apache::lonlocal::texthash (
domain => 'Domain role',
@@ -7790,6 +7717,28 @@ sub print_privacy {
$datatable .= '';
$itemcount ++;
}
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '
'.$titles{'notify'}.'
'.
+ '
';
+ if ((@instdoms > 1) || (keys(%by_location) > 0)) {
+ my %curr;
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{'notify'} ne '') {
+ map {$curr{$_}=1;} split(/,/,$settings->{'notify'});
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox',
+ 'privacy_notify',%curr);
+ if ($numdc > 0) {
+ $datatable .= $table;
+ } else {
+ $datatable .= &mt('There are no active Domain Coordinators');
+ }
+ } else {
+ $datatable .= &mt('Nothing to set here, as there are no other domains');
+ }
+ $datatable .='
';
} elsif ($position eq 'middle') {
if ((@instdoms > 1) || (keys(%by_location) > 0)) {
if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
@@ -8203,7 +8152,7 @@ sub password_rules {
max => 'Maximum password length',
chars => 'Required characters',
);
- } elsif ($prefix eq 'secrets') {
+ } elsif (($prefix eq 'ltisecrets') || ($prefix eq 'toolsecrets')) {
%titles = &Apache::lonlocal::texthash (
min => 'Minimum secret length',
max => 'Maximum secret length',
@@ -8226,7 +8175,7 @@ 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};
}
@@ -8369,7 +8318,7 @@ sub print_wafproxy {
my %config = &Apache::lonnet::get_dom('configuration',['wafproxy'],$domain);
if (ref($config{'wafproxy'}) eq 'HASH') {
$aliases{$domain} = $config{'wafproxy'}{'alias'};
- if (exists($config{'wafproxy'}{'saml'})) {
+ if (exists($config{'wafproxy'}{'saml'})) {
$saml{$domain} = $config{'wafproxy'}{'saml'};
}
foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
@@ -8434,10 +8383,10 @@ sub print_wafproxy {
(' 'x2).''.
&mt('Alias used for SSO Auth').': '.
''.
- &mt('No').''.
+ &mt('No').''.
''.
&mt('Yes').''.
- '';
+ '';
}
$aliasrows .= '';
$aliasinfo{$dom_in_effect} .= $aliasrows;
@@ -9347,7 +9296,7 @@ sub print_loadbalancing {
no => ' checked="checked"',
);
my %balcookiechecked = (
- no => ' checked="checked"',
+ no => ' checked="checked"',
);
foreach my $sparetype (@sparestypes) {
my $targettable;
@@ -9702,8 +9651,8 @@ 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',
@@ -9934,7 +9883,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,
@@ -10071,7 +10020,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,
@@ -10098,8 +10047,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,
@@ -10201,7 +10150,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') {
@@ -10224,10 +10173,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.'"';
@@ -10242,10 +10191,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',
@@ -10370,7 +10319,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 '') {
@@ -10688,7 +10637,7 @@ sub print_defaults {
if ($defaults{$item.'_'.$field}) {
$checkedon = $checkedoff;
$checkedoff = '';
- }
+ }
$datatable .= '
'.
''.$titles->{$field}.' '.
''.&mt('Yes').''.
@@ -11027,10 +10976,13 @@ 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) =
- &publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron',
- '','',$newfile);
- if ($result ne 'ok') {
+ &Apache::lonconfigsettings::publishlogo($r,'copy',$legacyfile,$dom,$confname,
+ 'scantron','','',$newfile,$modified);
+ if ($result eq 'ok') {
+ &update_modify_urls($r,$modified);
+ } else {
$error = &mt("An error occurred publishing the [_1] bubblesheet format file in RES space. Error was: [_2].",$newfile,$result);
}
}
@@ -11514,7 +11466,7 @@ sub defaults_javascript {
function portalExtras(caller) {
var x = caller.value;
var y = new Array('email','web');
- for (var i=0; i 0) {
@@ -11610,7 +11562,7 @@ sub passwords_javascript {
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 'secrets') {
+ } elsif (($prefix eq 'ltisecrets') || ($prefix eq 'toolsecrets')) {
%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).',
@@ -11618,7 +11570,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) {
@@ -12012,7 +11964,6 @@ sub modifiable_userdata_row {
'
';
my $rem;
my %checks;
- my %current;
if (ref($settings) eq 'HASH') {
my $hashref;
if ($context eq 'lti') {
@@ -12038,7 +11989,7 @@ sub modifiable_userdata_row {
}
}
}
- if (ref($hashref) eq 'HASH') {
+ if (ref($hashref) eq 'HASH') {
foreach my $field (@fields) {
if ($hashref->{$field}) {
if ($role eq 'emailusername') {
@@ -12050,7 +12001,6 @@ sub modifiable_userdata_row {
}
}
}
-
my $total = scalar(@fields);
for (my $i=0; $i<$total; $i++) {
$rem = $i%($numinrow);
@@ -12139,15 +12089,19 @@ sub insttypes_row {
my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rowtotal,$onclick,
$customcss,$rowstyle) = @_;
my %lt = &Apache::lonlocal::texthash (
- cansearch => 'Users allowed to search',
+ cansearch => 'Users allowed to search',
statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
- lockablenames => 'User preference to lock name',
- selfassign => 'Self-reportable affiliations',
- overrides => "Override domain's helpdesk settings based on requester's affiliation",
+ lockablenames => 'User preference to lock name',
+ selfassign => 'Self-reportable affiliations',
+ overrides => "Override domain's helpdesk settings based on requester's affiliation",
+ webdav => 'WebDAV access available',
+ authorquota => 'Authoring Space quota (MB)',
);
- my $showdom;
+ my ($showdom,$defaultquota);
if ($context eq 'cansearch') {
$showdom = ' ('.$dom.')';
+ } elsif ($context eq 'authorquota') {
+ $defaultquota = 500;
}
my $class = 'LC_left_item';
if ($context eq 'statustocreate') {
@@ -12184,25 +12138,44 @@ sub insttypes_row {
}
$output .= '
';
}
- my $check = ' ';
- if (ref($settings) eq 'HASH') {
- if (ref($settings->{$context}) eq 'ARRAY') {
- if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {
- $check = ' checked="checked" ';
- }
- } elsif (ref($settings->{$context}) eq 'HASH') {
- if (ref($settings->{$context}->{$types->[$i]}) eq 'HASH') {
+ if ($context eq 'authorquota') {
+ my $currquota;
+ if ($settings->{$context}->{$types->[$i]} =~ /^\d+$/) {
+ $currquota = $settings->{$context}->{$types->[$i]};
+ } else {
+ $currquota = $defaultquota;
+ }
+ $output .= '
';
- }
- if ($errors) {
- $resulttext .= &mt('The following errors occurred: ').'
'.
- $errors.'
';
}
- return $resulttext;
}
-sub process_ltitools_image {
- my ($r,$dom,$confname,$caller,$itemid,$configuserok,$switchserver,$author_ok) = @_;
- my $filename = $env{'form.'.$caller.'.filename'};
- my ($error,$url);
- my ($width,$height) = (21,21);
- if ($configuserok eq 'ok') {
- if ($switchserver) {
- $error = &mt('Upload of Tool Provider (LTI) icon is not permitted to this server: [_1]',
- $switchserver);
- } elsif ($author_ok eq 'ok') {
- my ($result,$imageurl,$madethumb) =
- &publishlogo($r,'upload',$caller,$dom,$confname,
- "ltitools/$itemid/icon",$width,$height);
- if ($result eq 'ok') {
- if ($madethumb) {
- my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
- my $imagethumb = "$path/tn-".$imagefile;
- $url = $imagethumb;
- } else {
- $url = $imageurl;
- }
- } else {
- $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
+sub store_security {
+ my ($dom,$context,$secchanges,$newkeyset,$keystore) = @_;
+ return unless ((ref($secchanges) eq 'HASH') && (ref($newkeyset) eq 'HASH') &&
+ (ref($keystore) eq 'HASH'));
+ if (keys(%{$secchanges})) {
+ if ($secchanges->{'private'}) {
+ my $who = &escape($env{'user.name'}.':'.$env{'user.domain'});
+ foreach my $hostid (keys(%{$newkeyset})) {
+ my $storehash = {
+ key => $newkeyset->{$hostid},
+ who => $env{'user.name'}.':'.$env{'user.domain'},
+ };
+ $keystore->{$hostid} = &Apache::lonnet::store_dom($storehash,$context,'private',
+ $dom,$hostid);
}
- } else {
- $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$author_ok);
}
- } else {
- $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$configuserok);
}
- return ($url,$error);
}
-sub get_ltitools_id {
- my ($cdom,$title) = @_;
- # get lock on ltitools db
- my $lockhash = {
- lock => $env{'user.name'}.
- ':'.$env{'user.domain'},
- };
- my $tries = 0;
- my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
- my ($id,$error);
-
- while (($gotlock ne 'ok') && ($tries<10)) {
- $tries ++;
- sleep (0.1);
- $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
- }
- if ($gotlock eq 'ok') {
- my %currids = &Apache::lonnet::dump_dom('ltitools',$cdom);
- if ($currids{'lock'}) {
- delete($currids{'lock'});
- if (keys(%currids)) {
- my @curr = sort { $a <=> $b } keys(%currids);
- if ($curr[-1] =~ /^\d+$/) {
- $id = 1 + $curr[-1];
- }
+sub lti_security_results {
+ my ($dom,$context,$secchanges,$newsec,$newkeyset,$keystore) = @_;
+ my $output;
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
+ my $needs_update;
+ foreach my $item (keys(%{$secchanges})) {
+ if ($item eq 'encrypt') {
+ $needs_update = 1;
+ my %encrypted;
+ if ($context eq 'lti') {
+ %encrypted = (
+ crs => {
+ on => &mt('Encryption of stored link protection secrets defined in courses enabled'),
+ off => &mt('Encryption of stored link protection secrets defined in courses disabled'),
+ },
+ dom => {
+ on => &mt('Encryption of stored link protection secrets defined in domain enabled'),
+ off => &mt('Encryption of stored link protection secrets defined in domain disabled'),
+ },
+ consumers => {
+ on => &mt('Encryption of stored consumer secrets defined in domain enabled'),
+ off => &mt('Encryption of stored consumer secrets defined in domain disabled'),
+ },
+ );
} else {
- $id = 1;
+ %encrypted = (
+ crs => {
+ on => &mt('Encryption of stored external tool secrets defined in courses enabled'),
+ off => &mt('Encryption of stored external tool secrets defined in courses disabled'),
+ },
+ dom => {
+ on => &mt('Encryption of stored external tool secrets defined in domain enabled'),
+ off => &mt('Encryption of stored external tool secrets defined in domain disabled'),
+ },
+ );
+
}
- if ($id) {
- unless (&Apache::lonnet::newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') {
- $error = 'nostore';
+ my @types= ('crs','dom');
+ if ($context eq 'lti') {
+ foreach my $type (@types) {
+ undef($domdefaults{'linkprotenc_'.$type});
+ }
+ push(@types,'consumers');
+ undef($domdefaults{'ltienc_consumers'});
+ } elsif ($context eq 'ltitools') {
+ foreach my $type (@types) {
+ undef($domdefaults{'toolenc_'.$type});
+ }
+ }
+ foreach my $type (@types) {
+ my $shown = $encrypted{$type}{'off'};
+ if (ref($newsec->{$item}) eq 'HASH') {
+ if ($newsec->{$item}{$type}) {
+ if ($context eq 'lti') {
+ if ($type eq 'consumers') {
+ $domdefaults{'ltienc_consumers'} = 1;
+ } else {
+ $domdefaults{'linkprotenc_'.$type} = 1;
+ }
+ } elsif ($context eq 'ltitools') {
+ $domdefaults{'toolenc_'.$type} = 1;
+ }
+ $shown = $encrypted{$type}{'on'};
+ }
+ }
+ $output .= '
'.$shown.'
';
+ }
+ } elsif ($item eq 'rules') {
+ my %titles = &Apache::lonlocal::texthash(
+ min => 'Minimum password length',
+ max => 'Maximum password length',
+ chars => 'Required characters',
+ );
+ foreach my $rule ('min','max') {
+ if ($newsec->{rules}{$rule} eq '') {
+ if ($rule eq 'min') {
+ $output .= '
'.&mt('[_1] not set.',$titles{$rule});
+ ' '.&mt('Default of [_1] will be used',
+ $Apache::lonnet::passwdmin).'
';
+ } else {
+ $output .= '
'.&mt('[_1] set to none',$titles{$rule}).'
';
+ }
+ } else {
+ $output .= '
'.&mt('[_1] set to [_2]',$titles{$rule},$newsec->{rules}{$rule}).'
';
+ }
+ }
+ if (ref($newsec->{'rules'}{'chars'}) eq 'ARRAY') {
+ if (@{$newsec->{'rules'}{'chars'}} > 0) {
+ my %rulenames = &Apache::lonlocal::texthash(
+ uc => 'At least one upper case letter',
+ lc => 'At least one lower case letter',
+ num => 'At least one number',
+ spec => 'At least one non-alphanumeric',
+ );
+ my $needed = '
'.&mt('Encryption key for storage of shared secrets saved for [_1]',$hostid).'
';
+ unless (grep(/^\Q$hostid\E$/,@privhosts)) {
+ push(@privhosts,$hostid);
+ }
+ }
+ }
+ if (@privhosts) {
+ if ($context eq 'lti') {
+ $domdefaults{'ltiprivhosts'} = \@privhosts;
+ } elsif ($context eq 'ltitools') {
+ $domdefaults{'toolprivhosts'} = \@privhosts;
+ }
+ }
+ }
+ } elsif ($item eq 'linkprot') {
+ next;
}
- my $dellockoutcome = &Apache::lonnet::del_dom('ltitools',['lock'],$cdom);
- } else {
- $error = 'nolock';
}
- return ($id,$error);
+ if ($needs_update) {
+ my $cachetime = 24*60*60;
+ &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
+ }
+ return $output;
}
sub modify_proctoring {
@@ -15882,9 +15588,11 @@ sub process_proctoring_image {
$error = &mt('Upload of Remote Proctoring Provider icon is not permitted to this server: [_1]',
$switchserver);
} elsif ($author_ok eq 'ok') {
+ my $modified = [];
my ($result,$imageurl,$madethumb) =
- &publishlogo($r,'upload',$caller,$dom,$confname,
- "proctoring/$provider/icon",$width,$height);
+ &Apache::lonconfigsettings::publishlogo($r,'upload',$caller,$dom,$confname,
+ "proctoring/$provider/icon",$width,$height,
+ '',$modified);
if ($result eq 'ok') {
if ($madethumb) {
my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
@@ -15893,6 +15601,7 @@ sub process_proctoring_image {
} else {
$url = $imageurl;
}
+ &update_modify_urls($r,$modified);
} else {
$error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
}
@@ -15908,7 +15617,7 @@ sub process_proctoring_image {
sub modify_lti {
my ($r,$dom,$action,$lastactref,%domconfig) = @_;
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
- my ($newid,@allpos,%changes,%confhash,%encconfig,$errors,$resulttext);
+ my ($newid,@allpos,%changes,%confhash,%ltienc,$errors,$resulttext);
my (%posslti,%posslticrs,%posscrstype);
my @courseroles = ('cc','in','ta','ep','st');
my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
@@ -15929,81 +15638,9 @@ sub modify_lti {
map { $posscrstype{$_} = 1; } @coursetypes;
my %menutitles = <imenu_titles();
+ my (%currltisec,%secchanges,%newltisec,%newltienc,%newkeyset);
- my (%currltisec,%secchanges,%newltisec,%newltienc,%keyset,%newkeyset);
- $newltisec{'private'}{'keys'} = [];
- $newltisec{'encrypt'} = {};
- $newltisec{'rules'} = {};
- $newltisec{'linkprot'} = {};
- if (ref($domconfig{'ltisec'}) eq 'HASH') {
- %currltisec = %{$domconfig{'ltisec'}};
- if (ref($currltisec{'linkprot'}) eq 'HASH') {
- foreach my $id (keys(%{$currltisec{'linkprot'}})) {
- unless ($id =~ /^\d+$/) {
- delete($currltisec{'linkprot'}{$id});
- }
- }
- }
- if (ref($currltisec{'private'}) eq 'HASH') {
- if (ref($currltisec{'private'}{'keys'}) eq 'ARRAY') {
- $newltisec{'private'}{'keys'} = $currltisec{'private'}{'keys'};
- map { $keyset{$_} = 1; } @{$currltisec{'private'}{'keys'}};
- }
- }
- }
- foreach my $item ('crs','dom','consumers') {
- my $formelement;
- if ($item eq 'consumers') {
- $formelement = 'form.ltisec_'.$item;
- } else {
- $formelement = 'form.ltisec_'.$item.'linkprot';
- }
- if ($env{$formelement}) {
- $newltisec{'encrypt'}{$item} = 1;
- if (ref($currltisec{'encrypt'}) eq 'HASH') {
- unless ($currltisec{'encrypt'}{$item}) {
- $secchanges{'encrypt'} = 1;
- }
- } else {
- $secchanges{'encrypt'} = 1;
- }
- } elsif (ref($currltisec{'encrypt'}) eq 'HASH') {
- if ($currltisec{'encrypt'}{$item}) {
- $secchanges{'encrypt'} = 1;
- }
- }
- }
- unless (exists($currltisec{'rules'})) {
- $currltisec{'rules'} = {};
- }
- &password_rule_changes('secrets',$newltisec{'rules'},$currltisec{'rules'},\%secchanges);
-
- my @ids=&Apache::lonnet::current_machine_ids();
- my %servers = &Apache::lonnet::get_servers($dom,'library');
-
- foreach my $hostid (keys(%servers)) {
- if (($hostid ne '') && (grep(/^\Q$hostid\E$/,@ids))) {
- my $newkey;
- my $keyitem = 'form.ltisec_privkey_'.$hostid;
- if (exists($env{$keyitem})) {
- $env{$keyitem} =~ s/(`)/'/g;
- if ($keyset{$hostid}) {
- if ($env{'form.ltisec_changeprivkey_'.$hostid}) {
- if ($env{$keyitem} ne '') {
- $secchanges{'private'} = 1;
- $newkeyset{$hostid} = $env{$keyitem};
- }
- }
- } elsif ($env{$keyitem} ne '') {
- unless (grep(/^\Q$hostid\E$/,@{$newltisec{'private'}{'keys'}})) {
- push(@{$newltisec{'private'}{'keys'}},$hostid);
- }
- $secchanges{'private'} = 1;
- $newkeyset{$hostid} = $env{$keyitem};
- }
- }
- }
- }
+ &fetch_secrets($dom,'ltisec',\%domconfig,\%currltisec,\%secchanges,\%newltisec,\%newkeyset);
my (%linkprotchg,$linkprotoutput,$is_home);
my $proterror = &Apache::courseprefs::process_linkprot($dom,'',$currltisec{'linkprot'},
@@ -16094,29 +15731,43 @@ sub modify_lti {
}
}
}
+ my (%keystore,$secstored);
+ if ($is_home) {
+ &store_security($dom,'lti',\%secchanges,\%newkeyset,\%keystore);
+ }
+
+ my ($cipher,$privnum);
+ if ((@items > 0) && ($is_home)) {
+ ($cipher,$privnum) = &get_priv_creds($dom,$home,$secchanges{'encrypt'},
+ $newltisec{'encrypt'},$keystore{$home});
+ }
foreach my $idx (@items) {
my $itemid = $itemids{$idx};
next unless ($itemid);
+ my %currlti;
+ unless ($idx eq 'add') {
+ if (ref($domconfig{$action}) eq 'HASH') {
+ if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
+ %currlti = %{$domconfig{$action}{$itemid}};
+ }
+ }
+ }
my $position = $env{'form.lti_pos_'.$itemid};
$position =~ s/\D+//g;
if ($position ne '') {
$allpos[$position] = $itemid;
}
- foreach my $item ('consumer','key','secret','lifetime','requser','crsinc') {
+ foreach my $item ('consumer','lifetime','requser','crsinc') {
my $formitem = 'form.lti_'.$item.'_'.$idx;
$env{$formitem} =~ s/(`)/'/g;
if ($item eq 'lifetime') {
$env{$formitem} =~ s/[^\d.]//g;
}
if ($env{$formitem} ne '') {
- if (($item eq 'key') || ($item eq 'secret')) {
- $encconfig{$itemid}{$item} = $env{$formitem};
- } else {
- $confhash{$itemid}{$item} = $env{$formitem};
- unless (($idx eq 'add') || ($changes{$itemid})) {
- if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
- $changes{$itemid} = 1;
- }
+ $confhash{$itemid}{$item} = $env{$formitem};
+ unless (($idx eq 'add') || ($changes{$itemid})) {
+ if ($currlti{$item} ne $confhash{$itemid}{$item}) {
+ $changes{$itemid} = 1;
}
}
}
@@ -16257,27 +15908,27 @@ sub modify_lti {
unless (($idx eq 'add') || ($changes{$itemid})) {
if ($confhash{$itemid}{'crsinc'}) {
foreach my $field ('mapcrs','storecrs','makecrs','section','passback','roster') {
- if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
+ if ($currlti{$field} ne $confhash{$itemid}{$field}) {
$changes{$itemid} = 1;
}
}
unless ($changes{$itemid}) {
- if ($domconfig{$action}{$itemid}{'passback'} eq $confhash{$itemid}{'passback'}) {
- if ($domconfig{$action}{$itemid}{'passbackformat'} ne $confhash{$itemid}{'passbackformat'}) {
+ if ($currlti{'passback'} eq $confhash{$itemid}{'passback'}) {
+ if ($currlti{'passbackformat'} ne $confhash{$itemid}{'passbackformat'}) {
$changes{$itemid} = 1;
}
}
}
foreach my $field ('mapcrstype','selfenroll') {
unless ($changes{$itemid}) {
- if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
+ if (ref($currlti{$field}) eq 'ARRAY') {
if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
- my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
+ my @diffs = &Apache::loncommon::compare_arrays($currlti{$field},
$confhash{$itemid}{$field});
if (@diffs) {
$changes{$itemid} = 1;
}
- } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
+ } elsif (@{$currlti{$field}} > 0) {
$changes{$itemid} = 1;
}
} elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
@@ -16288,10 +15939,10 @@ sub modify_lti {
}
}
unless ($changes{$itemid}) {
- if (ref($domconfig{$action}{$itemid}{'maproles'}) eq 'HASH') {
+ if (ref($currlti{'maproles'}) eq 'HASH') {
if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
- foreach my $ltirole (keys(%{$domconfig{$action}{$itemid}{'maproles'}})) {
- if ($domconfig{$action}{$itemid}{'maproles'}{$ltirole} ne
+ foreach my $ltirole (keys(%{$currlti{'maproles'}})) {
+ if ($currlti{'maproles'}{$ltirole} ne
$confhash{$itemid}{'maproles'}{$ltirole}) {
$changes{$itemid} = 1;
last;
@@ -16300,13 +15951,13 @@ sub modify_lti {
unless ($changes{$itemid}) {
foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
if ($confhash{$itemid}{'maproles'}{$ltirole} ne
- $domconfig{$action}{$itemid}{'maproles'}{$ltirole}) {
+ $currlti{'maproles'}{$ltirole}) {
$changes{$itemid} = 1;
last;
}
}
}
- } elsif (keys(%{$domconfig{$action}{$itemid}{'maproles'}}) > 0) {
+ } elsif (keys(%{$currlti{'maproles'}}) > 0) {
$changes{$itemid} = 1;
}
} elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
@@ -16320,20 +15971,20 @@ sub modify_lti {
}
unless ($changes{$itemid}) {
foreach my $field ('mapuser','lcauth','lcauthparm','topmenu','inlinemenu','callback') {
- if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
+ if ($currlti{$field} ne $confhash{$itemid}{$field}) {
$changes{$itemid} = 1;
}
}
unless ($changes{$itemid}) {
foreach my $field ('makeuser','lcmenu') {
- if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
+ if (ref($currlti{$field}) eq 'ARRAY') {
if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
- my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
+ my @diffs = &Apache::loncommon::compare_arrays($currlti{$field},
$confhash{$itemid}{$field});
if (@diffs) {
$changes{$itemid} = 1;
}
- } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
+ } elsif (@{$currlti{$field}} > 0) {
$changes{$itemid} = 1;
}
} elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
@@ -16346,6 +15997,71 @@ sub modify_lti {
}
}
}
+ if ($is_home) {
+ my $keyitem = 'form.lti_key_'.$idx;
+ $env{$keyitem} =~ s/(`)/'/g;
+ if ($env{$keyitem} ne '') {
+ $ltienc{$itemid}{'key'} = $env{$keyitem};
+ unless ($changes{$itemid}) {
+ if ($currlti{'key'} ne $env{$keyitem}) {
+ $changes{$itemid} = 1;
+ }
+ }
+ }
+ my $secretitem = 'form.lti_secret_'.$idx;
+ $env{$secretitem} =~ s/(`)/'/g;
+ if ($currlti{'usable'}) {
+ if ($env{'form.lti_changesecret_'.$idx}) {
+ if ($env{$secretitem} ne '') {
+ if ($privnum && $cipher) {
+ $ltienc{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
+ $confhash{$itemid}{'cipher'} = $privnum;
+ } else {
+ $ltienc{$itemid}{'secret'} = $env{$secretitem};
+ }
+ $changes{$itemid} = 1;
+ }
+ } else {
+ $ltienc{$itemid}{'secret'} = $currlti{'secret'};
+ $confhash{$itemid}{'cipher'} = $currlti{'cipher'};
+ }
+ if (ref($ltienc{$itemid}) eq 'HASH') {
+ if (($ltienc{$itemid}{'key'} ne '') && ($ltienc{$itemid}{'secret'} ne '')) {
+ $confhash{$itemid}{'usable'} = 1;
+ }
+ }
+ } elsif ($env{$secretitem} ne '') {
+ if ($privnum && $cipher) {
+ $ltienc{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
+ $confhash{$itemid}{'cipher'} = $privnum;
+ } else {
+ $ltienc{$itemid}{'secret'} = $env{$secretitem};
+ }
+ if (ref($ltienc{$itemid}) eq 'HASH') {
+ if (($ltienc{$itemid}{'key'} ne '') && ($ltienc{$itemid}{'key'} ne '')) {
+ $confhash{$itemid}{'usable'} = 1;
+ }
+ }
+ $changes{$itemid} = 1;
+ }
+ }
+ unless ($changes{$itemid}) {
+ foreach my $key (keys(%currlti)) {
+ if (ref($currlti{$key}) eq 'HASH') {
+ if (ref($confhash{$itemid}{$key}) eq 'HASH') {
+ foreach my $innerkey (keys(%{$currlti{$key}})) {
+ unless (exists($confhash{$itemid}{$key}{$innerkey})) {
+ $changes{$itemid} = 1;
+ last;
+ }
+ }
+ } elsif (keys(%{$currlti{$key}}) > 0) {
+ $changes{$itemid} = 1;
+ }
+ }
+ last if ($changes{$itemid});
+ }
+ }
}
if (@allpos > 0) {
my $idx = 0;
@@ -16363,12 +16079,21 @@ sub modify_lti {
}
}
}
+
+ if ((keys(%changes) == 0) && (keys(%secchanges) == 0)) {
+ return &mt('No changes made.');
+ }
+
my %ltihash = (
$action => { %confhash }
);
- my %ltienchash = (
- $action => { %encconfig }
- );
+ my %ltienchash;
+
+ if ($is_home) {
+ %ltienchash = (
+ $action => { %ltienc }
+ );
+ }
if (keys(%secchanges)) {
$ltihash{'ltisec'} = \%newltisec;
if ($secchanges{'linkprot'}) {
@@ -16379,130 +16104,32 @@ sub modify_lti {
}
my $putresult = &Apache::lonnet::put_dom('configuration',\%ltihash,$dom);
if ($putresult eq 'ok') {
- my %keystore;
- if (keys(%secchanges)) {
- if ($secchanges{'private'}) {
- my $who = &escape($env{'user.name'}.':'.$env{'user.domain'});
- foreach my $hostid (keys(%newkeyset)) {
- my $storehash = {
- key => $newkeyset{$hostid},
- who => $env{'user.name'}.':'.$env{'user.domain'},
- };
- $keystore{$hostid} = &Apache::lonnet::store_dom($storehash,'lti','private',
- $dom,$hostid);
- }
- }
- if (ref($lastactref) eq 'HASH') {
- if (($secchanges{'encrypt'}) || ($secchanges{'private'})) {
- $lastactref->{'domdefaults'} = 1;
- }
- }
- }
- &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom,undef,1);
- if ((keys(%changes) == 0) && (keys(%secchanges) == 0)) {
- return &mt('No changes made.');
+ if (keys(%ltienchash)) {
+ &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom,undef,1);
}
$resulttext = &mt('Changes made:').'
';
if (keys(%secchanges) > 0) {
- foreach my $item (keys(%secchanges)) {
- if ($item eq 'encrypt') {
- my %encrypted = (
- crs => {
- on => &mt('Encryption of stored link protection secrets defined in courses enabled'),
- off => &mt('Encryption of stored link protection secrets defined in courses disabled'),
- },
- dom => {
- on => &mt('Encryption of stored link protection secrets defined in domain enabled'),
- off => &mt('Encryption of stored link protection secrets defined in domain disabled'),
- },
- consumers => {
- on => &mt('Encryption of stored consumer secrets defined in domain enabled'),
- off => &mt('Encryption of stored consumer secrets defined in domain disabled'),
- },
- );
- foreach my $type ('crs','dom','consumers') {
- my $shown = $encrypted{$type}{'off'};
- if (ref($newltisec{$item}) eq 'HASH') {
- if ($newltisec{$item}{$type}) {
- $shown = $encrypted{$type}{'on'};
- }
- }
- $resulttext .= '
'.$shown.'
';
- }
- } elsif ($item eq 'rules') {
- my %titles = &Apache::lonlocal::texthash(
- min => 'Minimum password length',
- max => 'Maximum password length',
- chars => 'Required characters',
- );
- foreach my $rule ('min','max') {
- if ($newltisec{rules}{$rule} eq '') {
- if ($rule eq 'min') {
- $resulttext .= '
'.&mt('[_1] not set.',$titles{$rule});
- ' '.&mt('Default of [_1] will be used',
- $Apache::lonnet::passwdmin).'
';
- } else {
- $resulttext .= '
'.&mt('[_1] set to none',$titles{$rule}).'
';
- }
- } else {
- $resulttext .= '
'.&mt('[_1] set to [_2]',$titles{$rule},$newltisec{rules}{$rule}).'
';
- }
- }
- if (ref($newltisec{'rules'}{'chars'}) eq 'ARRAY') {
- if (@{$newltisec{'rules'}{'chars'}} > 0) {
- my %rulenames = &Apache::lonlocal::texthash(
- uc => 'At least one upper case letter',
- lc => 'At least one lower case letter',
- num => 'At least one number',
- spec => 'At least one non-alphanumeric',
- );
- my $needed = '