';
}
$itemcount ++;
@@ -2322,7 +2387,7 @@ sub print_quotas {
@options = ('norequest','approval','automatic');
%titles = &authorrequest_titles();
} else {
- @usertools = ('aboutme','blog','webdav','portfolio');
+ @usertools = ('aboutme','blog','webdav','portfolio','timezone');
%titles = &tool_titles();
}
if (ref($types) eq 'ARRAY') {
@@ -2426,9 +2491,12 @@ 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} == 0) {
+ if (!$settings->{$item}->{$type}) {
$checked = '';
} elsif ($settings->{$item}->{$type} == 1) {
$checked = 'checked="checked" ';
@@ -3365,10 +3433,19 @@ ENDSCRIPT
sub lti_javascript {
- my ($settings) = @_;
- my $togglejs = <i_toggle_js();
+ my ($dom,$settings) = @_;
+ my $togglejs = <i_toggle_js($dom);
+ my $linkprot_js = &Apache::courseprefs::linkprot_javascript();
unless (ref($settings) eq 'HASH') {
- return $togglejs;
+ return $togglejs.'
+
+';
}
my (%ordered,$total,%jstext);
$total = scalar(keys(%{$settings}));
@@ -3430,6 +3507,9 @@ $jstext
}
return;
}
+
+$linkprot_js
+
// ]]>
@@ -3439,12 +3519,17 @@ ENDSCRIPT
}
sub lti_toggle_js {
+ my ($dom) = @_;
my %lcauthparmtext = &Apache::lonlocal::texthash (
localauth => 'Local auth argument',
krb => 'Kerberos domain',
);
my $crsincalert = &mt('"User\'s identity sent" needs to be set to "Yes" first,[_1] before setting "Course\'s identity sent" to "Yes"',"\n");
&js_escape(\$crsincalert);
+ my %servers = &Apache::lonnet::get_servers($dom,'library');
+ my $primary = &Apache::lonnet::domain($dom,'primary');
+ my $course_servers = "'".join("','",keys(%servers))."'";
+
return <<"ENDSCRIPT";
@@ -3688,6 +3774,41 @@ function toggleLastActiveDays(form) {
ENDSCRIPT
}
+sub autoenroll_javascript {
+ return <<"ENDSCRIPT";
+
+
+ENDSCRIPT
+}
+
sub saml_javascript {
return <<"ENDSCRIPT";
+
+ENDSCRIPT
+ } else {
+return <<"ENDSCRIPT";
+
@@ -11069,17 +11176,27 @@ ENDSCRIPT
}
sub passwords_javascript {
- my %intalert = &Apache::lonlocal::texthash (
- authcheck => 'Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.',
- 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).',
- );
+ my ($prefix) = @_;
+ my %intalert;
+ if ($prefix eq 'passwords') {
+ %intalert = &Apache::lonlocal::texthash (
+ authcheck => 'Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.',
+ 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')) {
+ %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).',
+ );
+ }
&js_escape(\%intalert);
my $defmin = $Apache::lonnet::passwdmin;
- my $intauthjs = <<"ENDSCRIPT";
+ my $intauthjs;
+ if ($prefix eq 'passwords') { $intauthjs = <<"ENDSCRIPT";
function warnIntAuth(field) {
if (field.name == 'intauth_check') {
@@ -11099,11 +11216,17 @@ function warnIntAuth(field) {
return;
}
-function warnIntPass(field) {
+ENDSCRIPT
+
+ }
+
+ $intauthjs .= <<"ENDSCRIPT";
+
+function warnInt$prefix(field) {
field.value.replace(/^\s+/,'');
field.value.replace(/\s+\$/,'');
var regexdigit=/^\\d+\$/;
- if (field.name == 'passwords_min') {
+ if (field.name == '${prefix}_min') {
if (field.value == '') {
alert('$intalert{passmin}');
field.value = '$defmin';
@@ -11123,7 +11246,7 @@ function warnIntPass(field) {
field.value = '';
}
if (field.value != '') {
- if (field.name == 'passwords_expire') {
+ if (field.name == '${prefix}_expire') {
var regexpposnum=/^\\d+(|\\.\\d*)\$/;
if (!regexpposnum.test(field.value)) {
alert('$intalert{passexp}');
@@ -11137,10 +11260,10 @@ function warnIntPass(field) {
}
} else {
if (!regexdigit.test(field.value)) {
- if (field.name == 'passwords_max') {
+ if (field.name == '${prefix}_max') {
alert('$intalert{passmax}');
} else {
- if (field.name == 'passwords_numsaved') {
+ if (field.name == '${prefix}_numsaved') {
alert('$intalert{passnum}');
}
}
@@ -11771,7 +11894,7 @@ sub modify_login {
my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl,
%curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon,
- %currsaml,%saml,%samltext,%samlimg,%samlalt,%samlurl,%samltitle,%samlnotsso);
+ %currsaml,%saml,%samltext,%samlimg,%samlalt,%samlurl,%samltitle,%samlwindow,%samlnotsso);
%title = ( coursecatalog => 'Display course catalog',
adminmail => 'Display administrator E-mail address',
helpdesk => 'Display "Contact Helpdesk" link',
@@ -11795,6 +11918,7 @@ sub modify_login {
$samlalt{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'alt'};
$samlimg{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'img'};
$samltitle{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'title'};
+ $samlwindow{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'window'};
$samlnotsso{$lonhost} = $domconfig{login}{'saml'}{$lonhost}{'notsso'};
}
}
@@ -11937,13 +12061,16 @@ sub modify_login {
if ($addedfile ne '') {
push(@allnew,$addedfile);
}
+ my $modified = [];
foreach my $lang (@allnew) {
my $formelem = 'loginhelpurl_'.$lang;
if ($lang eq $env{'form.loginhelpurl_add_lang'}) {
$formelem = 'loginhelpurl_add_file';
}
- (my $result,$newurl{$lang}) = &publishlogo($r,'upload',$formelem,$dom,$confname,
- "help/$lang",'','',$newfile{$lang});
+ (my $result,$newurl{$lang}) =
+ &Apache::lonconfigsettings::publishlogo($r,'upload',$formelem,$dom,$confname,
+ "help/$lang",'','',$newfile{$lang},
+ $modified);
if ($result eq 'ok') {
$loginhash{'login'}{'helpurl'}{$lang} = $newurl{$lang};
$changes{'helpurl'}{$lang} = 1;
@@ -11956,6 +12083,7 @@ sub modify_login {
}
}
}
+ &update_modify_urls($r,$modified);
} else {
$error = &mt("Upload of custom log-in help file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2]. Error was: [_3].",$confname,$dom,$author_ok);
}
@@ -12013,11 +12141,14 @@ sub modify_login {
if ($switchserver) {
$error = &mt("Upload of custom markup is not permitted to this server: [_1]",$switchserver);
} elsif ($author_ok eq 'ok') {
+ my $modified = [];
foreach my $lonhost (@newhosts) {
my $formelem = 'loginheadtag_'.$lonhost;
- (my $result,$newheadtagurls{$lonhost}) = &publishlogo($r,'upload',$formelem,$dom,$confname,
- "login/headtag/$lonhost",'','',
- $env{'form.loginheadtag_'.$lonhost.'.filename'});
+ (my $result,$newheadtagurls{$lonhost}) =
+ &Apache::lonconfigsettings::publishlogo($r,'upload',$formelem,$dom,$confname,
+ "login/headtag/$lonhost",'','',
+ $env{'form.loginheadtag_'.$lonhost.'.filename'},
+ $modified);
if ($result eq 'ok') {
$loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $newheadtagurls{$lonhost};
$changes{'headtag'}{$lonhost} = 1;
@@ -12034,6 +12165,7 @@ sub modify_login {
}
}
}
+ &update_modify_urls($r,$modified);
} else {
$error = &mt("Upload of custom markup file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2]. Error was: [_3].",$confname,$dom,$author_ok);
}
@@ -12052,10 +12184,13 @@ sub modify_login {
if ($env{'form.saml_img_'.$lonhost.'.filename'}) {
push(@newsamlimgs,$lonhost);
}
- foreach my $item ('text','alt','url','title','notsso') {
+ foreach my $item ('text','alt','url','title','window','notsso') {
$env{'form.saml_'.$item.'_'.$lonhost} =~ s/^\s+|\s+$//g;
}
if ($saml{$lonhost}) {
+ if ($env{'form.saml_window_'.$lonhost} ne '1') {
+ $env{'form.saml_window_'.$lonhost} = '';
+ }
if (grep(/^\Q$lonhost\E$/,@delsamlimg)) {
#FIXME Need to obsolete published image
delete($currsaml{$lonhost}{'img'});
@@ -12073,13 +12208,16 @@ sub modify_login {
if ($env{'form.saml_title_'.$lonhost} ne $samltitle{$lonhost}) {
$changes{'saml'}{$lonhost} = 1;
}
+ if ($env{'form.saml_window_'.$lonhost} ne $samlwindow{$lonhost}) {
+ $changes{'saml'}{$lonhost} = 1;
+ }
if ($env{'form.saml_notsso_'.$lonhost} ne $samlnotsso{$lonhost}) {
$changes{'saml'}{$lonhost} = 1;
}
} else {
$changes{'saml'}{$lonhost} = 1;
}
- foreach my $item ('text','alt','url','title','notsso') {
+ foreach my $item ('text','alt','url','title','window','notsso') {
$currsaml{$lonhost}{$item} = $env{'form.saml_'.$item.'_'.$lonhost};
}
} else {
@@ -12102,11 +12240,14 @@ sub modify_login {
if ($switchserver) {
$error = &mt("Upload of SSO Button Image is not permitted to this server: [_1].",$switchserver);
} elsif ($author_ok eq 'ok') {
+ my $modified = [];
foreach my $lonhost (@newsamlimgs) {
my $formelem = 'saml_img_'.$lonhost;
- my ($result,$imgurl) = &publishlogo($r,'upload',$formelem,$dom,$confname,
- "login/saml/$lonhost",'','',
- $env{'form.saml_img_'.$lonhost.'.filename'});
+ my ($result,$imgurl) =
+ &Apache::lonconfigsettings::publishlogo($r,'upload',$formelem,$dom,$confname,
+ "login/saml/$lonhost",'','',
+ $env{'form.saml_img_'.$lonhost.'.filename'},
+ $modified);
if ($result eq 'ok') {
$currsaml{$lonhost}{'img'} = $imgurl;
$loginhash{'login'}{'saml'}{$lonhost}{'img'} = $imgurl;
@@ -12117,6 +12258,7 @@ sub modify_login {
$errors .= '
'.$puberror.'
';
}
}
+ &update_modify_urls($r,$modified);
} else {
$error = &mt("Upload of SSO button image file(s) failed because an author role could not be assigned to a Domain Configuration user ([_1]) in domain: [_2]. Error was: [_3].",$confname,$dom,$author_ok);
}
@@ -12280,19 +12422,22 @@ sub modify_login {
alt => 'Alt text for button image',
url => 'SSO URL',
title => 'Tooltip for SSO link',
+ window => 'Pop-up window if iframe',
notsso => 'Text for non-SSO log-in',
);
foreach my $lonhost (sort(keys(%{$changes{$item}}))) {
if (ref($currsaml{$lonhost}) eq 'HASH') {
$resulttext .= '
'.&mt("$title{$item} in use for [_1]","$lonhost").
'
';
- foreach my $key ('text','img','alt','url','title','notsso') {
+ foreach my $key ('text','img','alt','url','title','window','notsso') {
if ($currsaml{$lonhost}{$key} eq '') {
$resulttext .= '
';
- }
- 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,$lastactref) = @_;
+ 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);
+ }
+ }
+ if (ref($lastactref) eq 'HASH') {
+ if (($secchanges->{'encrypt'}) || ($secchanges->{'private'})) {
+ $lastactref->{'domdefaults'} = 1;
}
- } 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 ($context,$secchanges,$newsec,$newkeyset,$keystore) = @_;
+ my $output;
+ foreach my $item (keys(%{$secchanges})) {
+ if ($item eq 'encrypt') {
+ 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') {
+ push(@types,'consumers');
+ }
+ foreach my $type (@types) {
+ my $shown = $encrypted{$type}{'off'};
+ if (ref($newsec->{$item}) eq 'HASH') {
+ if ($newsec->{$item}{$type}) {
+ $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 = '