[LON-CAPA-cvs] cvs: loncom / lond /auth lonauth.pm migrateuser.pm switchserver.pm /interface domainprefs.pm loncommon.pm lonconfigsettings.pm loncreateuser.pm lonmodifycourse.pm lonrequestcourse.pm lonuserutils.pm /lonnet/perl lonnet.pm /lti ltiauth.pm
raeburn
raeburn at source.lon-capa.org
Thu Mar 22 21:02:23 EDT 2018
raeburn Fri Mar 23 01:02:23 2018 EDT
Modified files:
/loncom/interface domainprefs.pm loncommon.pm lonconfigsettings.pm
loncreateuser.pm lonmodifycourse.pm
lonrequestcourse.pm lonuserutils.pm
/loncom/auth lonauth.pm migrateuser.pm switchserver.pm
/loncom/lti ltiauth.pm
/loncom/lonnet/perl lonnet.pm
/loncom lond
Log:
- Bug 6754 LON-CAPA as LTI Provider
- Creation of new LON-CAPA user account available from an LTI Consumer.
- Creation of new LON-CAPA course available from an LTI Consumer.
- Self-enrollment in a LON-CAPA course available from an LTI Consumer.
-------------- next part --------------
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.324 loncom/interface/domainprefs.pm:1.325
--- loncom/interface/domainprefs.pm:1.324 Mon Jan 1 01:29:38 2018
+++ loncom/interface/domainprefs.pm Fri Mar 23 01:01:20 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.324 2018/01/01 01:29:38 raeburn Exp $
+# $Id: domainprefs.pm,v 1.325 2018/03/23 01:01:20 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -104,7 +104,7 @@
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 placement).
+(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).
@@ -1893,7 +1893,7 @@
my $typecount = 0;
my ($css_class,%titles);
if ($context eq 'requestcourses') {
- @usertools = ('official','unofficial','community','textbook','placement');
+ @usertools = ('official','unofficial','community','textbook','placement','lti');
@options =('norequest','approval','validate','autolimit');
%validations = &Apache::lonnet::auto_courserequest_checks($dom);
%titles = &courserequest_titles();
@@ -2357,7 +2357,7 @@
my ($settings,$rowtotal) = @_;
my $rownum = 0;
my ($output,%current);
- my @crstypes = ('official','unofficial','community','textbook','placement');
+ my @crstypes = ('official','unofficial','community','textbook','placement','lti');
if (ref($settings) eq 'HASH') {
if (ref($settings->{'uniquecode'}) eq 'HASH') {
foreach my $type (@crstypes) {
@@ -2806,6 +2806,10 @@
}
sub lti_toggle_js {
+ my %lcauthparmtext = &Apache::lonlocal::texthash (
+ localauth => 'Local auth argument',
+ krb => 'Kerberos domain',
+ );
return <<"ENDSCRIPT";
<script type="text/javascript">
// <![CDATA[
@@ -2883,6 +2887,28 @@
}
}
}
+ } else if (setting == 'lcauth') {
+ var numauth = form.elements['lti_lcauth_'+item].length;
+ if (numauth) {
+ for (var i=0; i<numauth; i++) {
+ if (form.elements['lti_lcauth_'+item][i].checked) {
+ if (document.getElementById('lti_'+setting+'_parmrow_'+item)) {
+ if ((form.elements['lti_'+setting+'_'+item][i].value == 'internal') || (form.elements['lti_'+setting+'_'+item][i].value == 'lti')) {
+ document.getElementById('lti_'+setting+'_parmrow_'+item).style.display = 'none';
+ } else {
+ document.getElementById('lti_'+setting+'_parmrow_'+item).style.display = 'table-row';
+ if (document.getElementById('lti_'+setting+'_parmtext_'+item)) {
+ if (form.elements['lti_'+setting+'_'+item][i].value == 'localauth') {
+ document.getElementById('lti_'+setting+'_parmtext_'+item).innerHTML = "$lcauthparmtext{'localauth'}";
+ } else {
+ document.getElementById('lti_'+setting+'_parmtext_'+item).innerHTML = "$lcauthparmtext{'krb'}";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
return;
}
@@ -4614,7 +4640,7 @@
'<input type="password" size="20" name="lti_secret_'.$i.'" value="'.$secret.'" />'.
'<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.lti_secret_'.$i.'.type='."'text'".' } else { this.form.lti_secret_'.$i.'.type='."'password'".' }" />'.&mt('Visible input').'</label>'.
'<input type="hidden" name="lti_id_'.$i.'" value="'.$item.'" /></span>'.
- '</fieldset>'.<i_options($i,$current,%lt).'</td></tr>';
+ '</fieldset>'.<i_options($i,$current,$itemcount,%lt).'</td></tr>';
$itemcount ++;
}
}
@@ -4647,7 +4673,7 @@
(' 'x2).
'<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="lti_secret_add" value="" />'.
'<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.lti_secret_add.type='."'text'".' } else { this.form.lti_secret_add.type='."'password'".' }" />'.&mt('Visible input').'</label></span> '."\n".
- '</fieldset>'.<i_options('add',undef,%lt).
+ '</fieldset>'.<i_options('add',undef,$itemcount,%lt).
'</td>'."\n".
'</tr>'."\n";
$$rowtotal ++;
@@ -4672,7 +4698,7 @@
}
sub lti_options {
- my ($num,$current,%lt) = @_;
+ my ($num,$current,$itemcount,%lt) = @_;
my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield);
$checked{'mapuser'}{'sourcedid'} = ' checked="checked"';
$checked{'mapcrs'}{'course_offering_sourcedid'} = ' checked="checked"';
@@ -4682,11 +4708,18 @@
$checked{'selfenroll'} = {};
$checked{'crssec'} = {};
$checked{'crssecsrc'} = {};
-
+ $checked{'lcauth'} = {};
+ if ($num eq 'add') {
+ $checked{'lcauth'}{'lti'} = ' checked="checked"';
+ }
my $userfieldsty = 'none';
my $crsfieldsty = 'none';
my $crssecfieldsty = 'none';
my $secsrcfieldsty = 'none';
+ my $lcauthparm;
+ my $lcauthparmstyle = 'display:none';
+ my $lcauthparmtext;
+ my $numinrow = 4;
if (ref($current) eq 'HASH') {
if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
@@ -4722,6 +4755,18 @@
$checked{'makeuser'}{$role} = ' checked="checked"';
}
}
+ if ($current->{'lcauth'} =~ /^(internal|localauth|krb4|krb5|lti)$/) {
+ $checked{'lcauth'}{$1} = ' checked="checked"';
+ unless (($current->{'lcauth'} eq 'lti') || ($current->{'lcauth'} eq 'internal')) {
+ $lcauthparm = $current->{'lcauthparm'};
+ $lcauthparmstyle = 'display:table-row';
+ if ($current->{'lcauth'} eq 'localauth') {
+ $lcauthparmtext = &mt('Local auth argument');
+ } else {
+ $lcauthparmtext = &mt('Kerberos domain');
+ }
+ }
+ }
if (ref($current->{'selfenroll'}) eq 'ARRAY') {
foreach my $role (@{$current->{'selfenroll'}}) {
$checked{'selfenroll'}{$role} = ' checked="checked"';
@@ -4746,15 +4791,25 @@
} else {
$checked{'makecrs'}{'N'} = ' checked="checked"';
$checked{'crssec'}{'N'} = ' checked="checked"';
+#FIXME
}
- my @coursetypes = ('official','unofficial','community','textbook','placement');
+ 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');
+ my %shortauth = (
+ internal => 'int',
+ krb4 => 'krb4',
+ krb5 => 'krb5',
+ localauth => 'loc'
+ );
+ my %authnames = &authtype_names();
my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
my @lticourseroles = qw(Learner Instructor TeachingAssistant Mentor);
my @courseroles = ('cc','in','ta','ep','st');
@@ -4762,6 +4817,7 @@
my $onclickcrs = ' onclick="toggleLTI(this.form,'."'crs','$num'".');"';
my $onclicksec = ' onclick="toggleLTI(this.form,'."'sec','$num'".');"';
my $onclicksecsrc = ' onclick="toggleLTI(this.form,'."'secsrc','$num'".')"';
+ my $onclicklcauth = ' onclick="toggleLTI(this.form,'."'lcauth','$num'".')"';
my $output = '<fieldset><legend>'.&mt('Mapping users').'</legend>'.
'<div class="LC_floatleft"><span class="LC_nobreak">'.&mt('LON-CAPA username').': ';
foreach my $option ('sourcedid','email','other') {
@@ -4803,6 +4859,29 @@
$checked{'makeuser'}{$ltirole}.' />'.$ltirole.'</label> </span> ';
}
$output .= '</fieldset>'.
+ '<fieldset><legend>'.&mt('New user accounts created for LTI users').'</legend>'.
+ '<table>'.
+ &modifiable_userdata_row('lti','instdata_'.$num,$current,$numinrow,$itemcount).
+ '</table>'.
+ '<table class="LC_nested"><tr><td class="LC_left_item">LON-CAPA Authentication</td>'.
+ '<td class="LC_left_item">';
+ foreach my $auth ('lti', at authtypes) {
+ my $authtext;
+ if ($auth eq 'lti') {
+ $authtext = &mt('None');
+ } else {
+ $authtext = $authnames{$shortauth{$auth}};
+ }
+ $output .= '<span class="LC_nobreak"><label><input type="radio" name="lti_lcauth_'.$num.
+ '" value="'.$auth.'"'.$checked{'lcauth'}{$auth}.$onclicklcauth.' />'.
+ $authtext.'</label></span> ';
+ }
+ $output .= '</td></tr>'.
+ '<tr id="lti_lcauth_parmrow_'.$num.'" style="'.$lcauthparmstyle.'">'.
+ '<td class="LC_right_item" colspan="2"><span class="LC_nobreak">'.
+ '<span id="lti_lcauth_parmtext_'.$num.'">'.$lcauthparmtext.'</span>'.
+ '<input type="text" name="lti_lcauthparm_'.$num.'" value="" /></span></td></tr>'.
+ '</table></fieldset>'.
'<fieldset><legend>'.&mt('Mapping courses').'</legend>'.
'<div class="LC_floatleft"><span class="LC_nobreak">'.
&mt('Unique course identifier').': ';
@@ -6445,8 +6524,9 @@
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)',
@@ -6558,7 +6638,7 @@
}
} else {
my @contexts = ('author','course','domain');
- my @authtypes = ('int','krb4','krb5','loc');
+ my @authtypes = ('int','krb4','krb5','loc','lti');
my %checked;
if (ref($settings) eq 'HASH') {
if (ref($settings->{'authtypes'}) eq 'HASH') {
@@ -7298,6 +7378,7 @@
krb4 => 'Kerberos 4',
krb5 => 'Kerberos 5',
loc => 'Local',
+ lti => 'LTI',
);
return %lt;
}
@@ -7366,12 +7447,13 @@
'<td><span class="LC_nobreak">'.$titles->{$item}.
'</span></td><td class="LC_right_item" colspan="3">';
if ($item eq 'auth_def') {
- my @authtypes = ('internal','krb4','krb5','localauth');
+ my @authtypes = ('internal','krb4','krb5','localauth','lti');
my %shortauth = (
internal => 'int',
krb4 => 'krb4',
krb5 => 'krb5',
- localauth => 'loc'
+ localauth => 'loc',
+ lti => 'lti',
);
my %authnames = &authtype_names();
foreach my $auth (@authtypes) {
@@ -8447,6 +8529,8 @@
} else {
$rolename = $role;
}
+ } elsif ($context eq 'lti') {
+ $rolename = &mt('Institutional data used (if available)');
} else {
if ($role eq 'cr') {
$rolename = &mt('Custom role');
@@ -8489,30 +8573,32 @@
'<td class="LC_left_item" colspan="2"><table>';
my $rem;
my %checks;
+ my %current;
if (ref($settings) eq 'HASH') {
- if (ref($settings->{$context}) eq 'HASH') {
+ my $hashref;
+ if ($context eq 'lti') {
+ if (ref($settings) eq 'HASH') {
+ $hashref = $settings->{'instdata'};
+ }
+ } elsif (ref($settings->{$context}) eq 'HASH') {
if (ref($settings->{$context}->{$role}) eq 'HASH') {
- my $hashref = $settings->{$context}->{$role};
- if ($role eq 'emailusername') {
- if ($statustype) {
- if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
- $hashref = $settings->{$context}->{$role}->{$statustype};
- if (ref($hashref) eq 'HASH') {
- foreach my $field (@fields) {
- if ($hashref->{$field}) {
- $checks{$field} = $hashref->{$field};
- }
- }
- }
- }
+ $hashref = $settings->{'lti_instdata'};
+ }
+ if ($role eq 'emailusername') {
+ if ($statustype) {
+ if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') {
+ $hashref = $settings->{$context}->{$role}->{$statustype};
}
- } else {
- if (ref($hashref) eq 'HASH') {
- foreach my $field (@fields) {
- if ($hashref->{$field}) {
- $checks{$field} = ' checked="checked" ';
- }
- }
+ }
+ }
+ }
+ if (ref($hashref) eq 'HASH') {
+ foreach my $field (@fields) {
+ if ($hashref->{$field}) {
+ if ($role eq 'emailusername') {
+ $checks{$field} = $hashref->{$field};
+ } else {
+ $checks{$field} = ' checked="checked" ';
}
}
}
@@ -8532,7 +8618,7 @@
unless ($role eq 'emailusername') {
if (exists($checks{$fields[$i]})) {
$check = $checks{$fields[$i]}
- } else {
+ } elsif ($context ne 'lti') {
if ($role eq 'st') {
if (ref($settings) ne 'HASH') {
$check = ' checked="checked" ';
@@ -8542,6 +8628,7 @@
}
$output .= '<td class="LC_left_item">'.
'<span class="LC_nobreak">';
+ my $prefix = 'canmodify';
if ($role eq 'emailusername') {
unless ($checks{$fields[$i]} =~ /^(required|optional)$/) {
$checks{$fields[$i]} = 'omit';
@@ -8552,13 +8639,16 @@
$checked='checked="checked" ';
}
$output .= '<label>'.
- '<input type="radio" name="canmodify_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.
+ '<input type="radio" name="'.$prefix.'_'.$item.'_'.$fields[$i].'" value="'.$option.'" '.$checked.'/>'.
&mt($option).'</label>'.(' ' x2);
}
$output .= '<i>'.$fieldtitles{$fields[$i]}.'</i>';
} else {
+ if ($context eq 'lti') {
+ $prefix = 'lti';
+ }
$output .= '<label>'.
- '<input type="checkbox" name="canmodify_'.$role.'" '.
+ '<input type="checkbox" name="'.$prefix.'_'.$role.'" '.
'value="'.$fields[$i].'"'.$check.'/>'.$fieldtitles{$fields[$i]}.
'</label>';
}
@@ -9968,7 +10058,7 @@
$context = $action;
}
if ($context eq 'requestcourses') {
- @usertools = ('official','unofficial','community','textbook','placement');
+ @usertools = ('official','unofficial','community','textbook','placement','lti');
@options =('norequest','approval','validate','autolimit');
%validations = &Apache::lonnet::auto_courserequest_checks($dom);
%titles = &courserequest_titles();
@@ -10017,7 +10107,7 @@
my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval');
@approvalnotify = sort(@approvalnotify);
$confhash{'notify'}{'approval'} = join(',', at approvalnotify);
- my @crstypes = ('official','unofficial','community','textbook','placement');
+ my @crstypes = ('official','unofficial','community','textbook','placement','lti');
my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode');
foreach my $type (@hasuniquecode) {
if (grep(/^\Q$type\E$/, at crstypes)) {
@@ -11361,10 +11451,13 @@
textbook => 'Textbook',
placement => 'Placement Test',
);
+ my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles();
my %lt = <i_names();
map { $posslti{$_} = 1; } @ltiroles;
map { $posslticrs{$_} = 1; } @lticourseroles;
map { $posscrstype{$_} = 1; } @coursetypes;
+
+#FIXME
my (@items,%deletions,%itemids);
if ($env{'form.lti_add'}) {
@@ -11453,6 +11546,30 @@
}
}
$confhash{$itemid}{'makeuser'} = \@makeuser;
+ if (@makeuser) {
+ my $lcauth = $env{'form.lti_lcauth_'.$idx};
+ if ($lcauth =~ /^(internal|krb4|krb5|localauth)$/) {
+ $confhash{$itemid}{'lcauth'} = $lcauth;
+ if ($lcauth ne 'internal') {
+ my $lcauthparm = $env{'form.lti_lcauthparm_'.$idx};
+ $lcauthparm =~ s/^(\s+|\s+)$//g;
+ $lcauthparm =~ s/`//g;
+ if ($lcauthparm ne '') {
+ $confhash{$itemid}{'lcauthparm'} = $lcauthparm;
+ }
+ }
+ } else {
+ $confhash{$itemid}{'lcauth'} = 'lti';
+ }
+ }
+ my @possinstdata = &Apache::loncommon::get_env_multiple('form.lti_instdata_'.$idx);
+ if (@possinstdata) {
+ foreach my $field (@possinstdata) {
+ if (exists($fieldtitles{$field})) {
+ push(@{$confhash{$itemid}{'instdata'}});
+ }
+ }
+ }
if (($env{'form.lti_mapcrs_'.$idx} eq 'course_offering_sourcedid') ||
($env{'form.lti_mapcrs_'.$idx} eq 'context_id')) {
$confhash{$itemid}{'mapcrs'} = $env{'form.lti_mapcrs_'.$idx};
@@ -11499,12 +11616,12 @@
}
}
unless (($idx eq 'add') || ($changes{$itemid})) {
- foreach my $field ('mapuser','mapcrs','section','passback','roster') {
+ foreach my $field ('mapuser','mapcrs','makecrs','section','passback','roster','lcauth','lcauthparm') {
if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
$changes{$itemid} = 1;
}
}
- foreach my $field ('makeuser','mapcrstype','selfenroll') {
+ foreach my $field ('makeuser','mapcrstype','selfenroll','instdata') {
unless ($changes{$itemid}) {
if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
@@ -11650,11 +11767,35 @@
if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
if (@{$confhash{$itemid}{'makeuser'}} > 0) {
$resulttext .= '<li>'.&mt('Following roles may create user accounts: [_1]',
- join(', ',@{$confhash{$itemid}{'makeuser'}})).'</li>';
+ join(', ',@{$confhash{$itemid}{'makeuser'}})).'<br />';
+ if ($confhash{$itemid}{'lcauth'} eq 'lti') {
+ $resulttext .= &mt('New users will only be able to authenticate via LTI').'</li>';
+ } else {
+ $resulttext .= &mt('New users will be assigned LON-CAPA authentication: [_1]',
+ $confhash{$itemid}{'lcauth'});
+ if ($confhash{$itemid}{'lcauth'} eq 'internal') {
+ $resulttext .= '; '.&mt('a randomly generated password will be created');
+ } elsif ($confhash{$itemid}{'lcauth'} eq 'localauth') {
+ if ($confhash{$itemid}{'lcauthparm'} ne '') {
+ $resulttext .= ' '.&mt('with argument: [_1]',$confhash{$itemid}{'lcauthparm'});
+ }
+ } else {
+ $resulttext .= '; '.&mt('Kerberos domain: [_1]',$confhash{$itemid}{'lcauthparm'});
+ }
+ }
+ $resulttext .= '</li>';
} else {
$resulttext .= '<li>'.&mt('User account creation not permitted.').'</li>';
}
}
+ if (ref($confhash{$itemid}{'instdata'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'instdata'}} > 0) {
+ $resulttext .= '<li>'.&mt('Institutional data will be used when creating a new user for: [_1]',
+ join(', ',map { $fieldtitles{$_}; } @{$confhash{$itemid}{'instdata'}})).'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('No institutional data used when creating a new user.').'</li>';
+ }
+ }
if ($confhash{$itemid}{'mapcrs'}) {
$resulttext .= '<li>'.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.'</li>';
}
@@ -12838,7 +12979,7 @@
}
my @authen_contexts = ('author','course','domain');
- my @authtypes = ('int','krb4','krb5','loc');
+ my @authtypes = ('int','krb4','krb5','loc','lti');
my %authhash;
foreach my $item (@authen_contexts) {
my @authallowed = &Apache::loncommon::get_env_multiple('form.'.$item.'_auth');
@@ -14020,7 +14161,7 @@
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
'portal_def','intauth_cost','intauth_check','intauth_switch');
- my @authtypes = ('internal','krb4','krb5','localauth');
+ my @authtypes = ('internal','krb4','krb5','localauth','lti');
foreach my $item (@items) {
$newvalues{$item} = $env{'form.'.$item};
if ($item eq 'auth_def') {
@@ -14212,6 +14353,7 @@
krb4 => 'krb4',
krb5 => 'krb5',
localauth => 'loc',
+ lti => 'lti',
);
$value = $authnames{$shortauth{$value}};
} elsif ($item eq 'intauth_switch') {
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1309 loncom/interface/loncommon.pm:1.1310
--- loncom/interface/loncommon.pm:1.1309 Fri Jan 12 13:33:38 2018
+++ loncom/interface/loncommon.pm Fri Mar 23 01:01:21 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1309 2018/01/12 13:33:38 raeburn Exp $
+# $Id: loncommon.pm,v 1.1310 2018/03/23 01:01:21 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -3027,6 +3027,8 @@
=item * authform_filesystem
+=item * authform_lti
+
=back
See loncreateuser.pm for invocation and use examples.
@@ -3443,14 +3445,69 @@
$fsyscheck.' onchange="'.$jscall.'" onclick="'.
$jscall.'"'.$disabled.' />';
}
- $autharg = '<input type="text" size="10" name="fsysarg" value=""'.
+ $autharg = '<input type="password" size="10" name="fsysarg" value=""'.
' onchange="'.$jscall.'"'.$disabled.' />';
$result = &mt
('[_1] Filesystem Authenticated (with initial password [_2])',
- '<label><input type="radio" name="login" value="fsys" '.
- $fsyscheck.'onchange="'.$jscall.'" onclick="'.$jscall.'"'.$disabled.' />',
- '</label><input type="password" size="10" name="fsysarg" value="" '.
- 'onchange="'.$jscall.'"'.$disabled.' />');
+ '<label>'.$authtype,'</label>'.$autharg);
+ return $result;
+}
+
+sub authform_lti {
+ my %in = (
+ formname => 'document.cu',
+ kerb_def_dom => 'MSU.EDU',
+ @_,
+ );
+ my ($lticheck,$result,$authtype,$autharg,$jscall,$disabled);
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ if ($in{'readonly'}) {
+ $disabled = ' disabled="disabled"';
+ }
+ if (defined($in{'curr_authtype'})) {
+ if ($in{'curr_authtype'} eq 'lti') {
+ if ($can_assign{'lti'}) {
+ $lticheck = 'checked="checked" ';
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifyuser') {
+ $lticheck = '';
+ }
+ }
+ } else {
+ $result = &mt('Currently LTI Authenticated.');
+ return $result;
+ }
+ }
+ } else {
+ if ($authnum == 1) {
+ $authtype = '<input type="hidden" name="login" value="lti" />';
+ }
+ }
+ if (!$can_assign{'lti'}) {
+ return;
+ } elsif ($authtype eq '') {
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifycourse') {
+ if ($authnum == 1) {
+ $authtype = '<input type="radio" name="login" value="lti"'.$disabled.' />';
+ }
+ }
+ }
+ }
+ $jscall = "javascript:changed_radio('lti',$in{'formname'});";
+ if (($authtype eq '') && (($in{'mode'} eq 'modifycourse') || ($in{'curr_authtype'} ne 'lti'))) {
+ $authtype = '<input type="radio" name="login" value="lti" '.
+ $lticheck.' onchange="'.$jscall.'" onclick="'.
+ $jscall.'"'.$disabled.' />';
+ }
+ $autharg = '<input type="hidden" name="ltiarg" value="" />';
+ if ($authtype) {
+ $result = &mt('[_1] LTI Authenticated',
+ '<label>'.$authtype.'</label>'.$autharg);
+ } else {
+ $result = '<b>'.&mt('LTI Authenticated').'</b>'.
+ $autharg;
+ }
return $result;
}
@@ -3464,6 +3521,7 @@
krb5 => 1,
int => 1,
loc => 1,
+ lti => 1,
);
my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
if (ref($domconfig{'usercreation'}) eq 'HASH') {
@@ -16187,13 +16245,14 @@
}
sub course_types {
- my @types = ('official','unofficial','community','textbook','placement');
+ my @types = ('official','unofficial','community','textbook','placement','lti');
my %typename = (
official => 'Official course',
unofficial => 'Unofficial course',
community => 'Community',
textbook => 'Textbook course',
placement => 'Placement test',
+ lti => 'LTI provider',
);
return (\@types,\%typename);
}
Index: loncom/interface/lonconfigsettings.pm
diff -u loncom/interface/lonconfigsettings.pm:1.41 loncom/interface/lonconfigsettings.pm:1.42
--- loncom/interface/lonconfigsettings.pm:1.41 Mon Jan 1 01:29:38 2018
+++ loncom/interface/lonconfigsettings.pm Fri Mar 23 01:01:21 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: lonconfigsettings.pm,v 1.41 2018/01/01 01:29:38 raeburn Exp $
+# $Id: lonconfigsettings.pm,v 1.42 2018/03/23 01:01:21 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -218,14 +218,16 @@
if (grep(/^lti$/, at actions)) {
$onload .= "toggleLTI(document.display,'user','add');".
"toggleLTI(document.display,'crs','add');".
- "toggleLTI(document.display,'sec','add');";
+ "toggleLTI(document.display,'sec','add');".
+ "toggleLTI(document.display,'lcauth','add');";
if (ref($values) eq 'HASH') {
if (ref($values->{'lti'}) eq 'HASH') {
my $numlti = scalar(keys(%{$values->{'lti'}}));
for (my $i=0; $i<$numlti; $i++) {
$onload .= "toggleLTI(document.display,'user','$i');".
"toggleLTI(document.display,'crs','$i');".
- "toggleLTI(document.display,'sec','$i');";
+ "toggleLTI(document.display,'sec','$i');".
+ "toggleLTI(document.display,'lcauth','$i');";
}
}
}
Index: loncom/interface/loncreateuser.pm
diff -u loncom/interface/loncreateuser.pm:1.448 loncom/interface/loncreateuser.pm:1.449
--- loncom/interface/loncreateuser.pm:1.448 Sat Nov 4 20:59:38 2017
+++ loncom/interface/loncreateuser.pm Fri Mar 23 01:01:21 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Create a user
#
-# $Id: loncreateuser.pm,v 1.448 2017/11/04 20:59:38 raeburn Exp $
+# $Id: loncreateuser.pm,v 1.449 2018/03/23 01:01:21 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -78,6 +78,7 @@
my $authformint;
my $authformfsys;
my $authformloc;
+my $authformlti;
sub initialize_authen_forms {
my ($dom,$formname,$curr_authtype,$mode) = @_;
@@ -88,7 +89,7 @@
domain => $dom,
);
my %abv_auth = &auth_abbrev();
- if ($curr_authtype =~ /^(krb4|krb5|internal|localauth|unix):(.*)$/) {
+ if ($curr_authtype =~ /^(krb4|krb5|internal|localauth|unix|lti):(.*)$/) {
my $long_auth = $1;
my $curr_autharg = $2;
my %abv_auth = &auth_abbrev();
@@ -107,6 +108,7 @@
$authformint = &Apache::loncommon::authform_internal(%param);
$authformfsys = &Apache::loncommon::authform_filesystem(%param);
$authformloc = &Apache::loncommon::authform_local(%param);
+ $authformlti = &Apache::loncommon::authform_lti(%param);
}
sub auth_abbrev {
@@ -116,6 +118,7 @@
internal => 'int',
localauth => 'loc',
unix => 'fsys',
+ lti => 'lti',
);
return %abv_auth;
}
@@ -253,14 +256,15 @@
'community' => 'Can request creation of communities',
'textbook' => 'Can request creation of textbook courses',
'placement' => 'Can request creation of placement tests',
+ 'lti' => 'Can request creation of LTI courses',
'requestauthor' => 'Can request author space',
);
if ($context eq 'requestcourses') {
%userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname,
'requestcourses.official','requestcourses.unofficial',
'requestcourses.community','requestcourses.textbook',
- 'requestcourses.placement');
- @usertools = ('official','unofficial','community','textbook','placement');
+ 'requestcourses.placement','requestcourses.lti');
+ @usertools = ('official','unofficial','community','textbook','placement','lti');
@options =('norequest','approval','autolimit','validate');
%validations = &Apache::lonnet::auto_courserequest_checks($ccdomain);
%reqtitles = &courserequest_titles();
@@ -543,6 +547,7 @@
community => 'Communities',
textbook => 'Textbook',
placement => 'Placement Tests',
+ lti => 'LTI Provider',
norequest => 'Not allowed',
approval => 'Approval by Dom. Coord.',
validate => 'With validation',
@@ -2200,7 +2205,7 @@
'ld' => "Login Data"
);
# Check for a bad authentication type
- if ($currentauth !~ /^(krb4|krb5|unix|internal|localauth):/) {
+ if ($currentauth !~ /^(krb4|krb5|unix|internal|localauth|lti):/) {
# bad authentication scheme
if (&Apache::lonnet::allowed('mau',$ccdomain)) {
&initialize_authen_forms($ccdomain,$formname);
@@ -2279,6 +2284,8 @@
$result = &mt('Currently using local (institutional) authentication.');
} elsif ($currentauth =~ /^unix:/) {
$result = &mt('Currently Filesystem Authenticated.');
+ } elsif ($currentauth =~ /^lti:/) {
+ $result = &mt('Currently LTi authenticated.');
}
$outcome = '<h3>'.$lt{'ld'}.'</h3>'.
&Apache::loncommon::start_data_table().
@@ -2317,6 +2324,9 @@
if ($can_assign{'loc'}) {
push(@authform_others,$authformloc);
}
+ if ($can_assign{'lti'}) {
+ push(@authform_others,$authformlti);
+ }
if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
$show_override_msg = 1;
}
@@ -2328,6 +2338,9 @@
if ($can_assign{'loc'}) {
push(@authform_others,$authformloc);
}
+ if ($can_assign{'lti'}) {
+ push(@authform_others,$authformlti);
+ }
if ($can_assign{'int'}) {
$show_override_msg = 1;
}
@@ -2342,6 +2355,9 @@
if ($can_assign{'loc'}) {
push(@authform_others,$authformloc);
}
+ if ($can_assign{'lti'}) {
+ push(@authform_others,$authformlti);
+ }
if ($can_assign{'fsys'}) {
$show_override_msg = 1;
}
@@ -2353,9 +2369,23 @@
if ($can_assign{'int'}) {
push(@authform_others,$authformint);
}
+ if ($can_assign{'lti'}) {
+ push(@authform_others,$authformlti);
+ }
if ($can_assign{'loc'}) {
$show_override_msg = 1;
}
+ } elsif ($currentauth=~/^lti:/) {
+ $authformcurrent=$authformlti;
+ if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
+ push(@authform_others,$authformkrb);
+ }
+ if ($can_assign{'int'}) {
+ push(@authform_others,$authformint);
+ }
+ if ($can_assign{'loc'}) {
+ push(@authform_others,$authformloc);
+ }
}
if ($show_override_msg) {
$authformcurrent = '<table><tr><td colspan="3">'.$authformcurrent.
@@ -2814,6 +2844,9 @@
$amode='localauth';
$genpwd=$env{'form.locarg'};
$genpwd=" " if (!$genpwd);
+ } elsif ($env{'form.login'} eq 'lti') {
+ $amode='lti';
+ $genpwd=" ";
} elsif (($env{'form.login'} eq 'nochange') ||
($env{'form.login'} eq '' )) {
# There is no need to tell the user we did not change what they
@@ -2833,7 +2866,7 @@
my (%alerts,%rulematch,%inst_results,%curr_rules);
my @userinfo = ('firstname','middlename','lastname','generation','permanentemail','id');
my @usertools = ('aboutme','blog','webdav','portfolio');
- my @requestcourses = ('official','unofficial','community','textbook','placement');
+ my @requestcourses = ('official','unofficial','community','textbook','placement','lti');
my @requestauthor = ('requestauthor');
my ($othertitle,$usertypes,$types) =
&Apache::loncommon::sorted_inst_types($env{'form.ccdomain'});
@@ -3299,7 +3332,7 @@
foreach my $key (keys(%changed)) {
if (($key eq 'official') || ($key eq 'unofficial') ||
($key eq 'community') || ($key eq 'textbook') ||
- ($key eq 'placement')) {
+ ($key eq 'placement') || ($key eq 'lti')) {
$newenvhash{'environment.requestcourses.'.$key} =
$changeHash{'requestcourses.'.$key};
if ($changeHash{'requestcourses.'.$key}) {
@@ -3509,6 +3542,7 @@
'community' => 'Can Request Communities',
'textbook' => 'Can Request Textbook Courses',
'placement' => 'Can Request Placement Tests',
+ 'lti' => 'Can Request LTI Courses',
'requestauthor' => 'Can Request Author Role',
'inststatus' => "Affiliation",
'prvs' => 'Previous Value:',
Index: loncom/interface/lonmodifycourse.pm
diff -u loncom/interface/lonmodifycourse.pm:1.92 loncom/interface/lonmodifycourse.pm:1.93
--- loncom/interface/lonmodifycourse.pm:1.92 Sat Apr 8 14:58:11 2017
+++ loncom/interface/lonmodifycourse.pm Fri Mar 23 01:01:21 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# handler for DC-only modifiable course settings
#
-# $Id: lonmodifycourse.pm,v 1.92 2017/04/08 14:58:11 raeburn Exp $
+# $Id: lonmodifycourse.pm,v 1.93 2018/03/23 01:01:21 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1277,6 +1277,8 @@
$curr_authtype = 'int';
} elsif ($enrollvar->{'authtype'} eq 'localauth' ) {
$curr_authtype = 'loc';
+ } elsif ($enrollvar->{'authtype'} eq 'lti' ) {
+ $curr_authtype = 'lti';
}
}
unless ($curr_authtype eq '') {
@@ -1297,7 +1299,8 @@
$authform{'krb'} = &Apache::loncommon::authform_kerberos(%param);
$authform{'int'} = &Apache::loncommon::authform_internal(%param);
$authform{'loc'} = &Apache::loncommon::authform_local(%param);
- foreach my $item ('krb','int','loc') {
+ $authform{'lti'} = &Apache::loncommon::authform_lti(%param);
+ foreach my $item ('krb','int','loc','lti') {
if ($authform{$item} ne '') {
$authenitems .= $authform{$item}.'<br />';
}
@@ -1363,6 +1366,8 @@
if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
$newattr{'autharg'} = $env{'form.locarg'};
}
+ } elsif ($env{'form.login'} eq 'lti') {
+ $newattr{'authtype'} = 'lti';
}
if ( $newattr{'authtype'}=~ /^krb/) {
if ($newattr{'autharg'} eq '') {
Index: loncom/interface/lonrequestcourse.pm
diff -u loncom/interface/lonrequestcourse.pm:1.102 loncom/interface/lonrequestcourse.pm:1.103
--- loncom/interface/lonrequestcourse.pm:1.102 Fri Aug 11 15:26:38 2017
+++ loncom/interface/lonrequestcourse.pm Fri Mar 23 01:01:21 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Request a course
#
-# $Id: lonrequestcourse.pm,v 1.102 2017/08/11 15:26:38 raeburn Exp $
+# $Id: lonrequestcourse.pm,v 1.103 2018/03/23 01:01:21 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -155,6 +155,23 @@
}
if ($canreq) {
+ if (($env{'form.crstype'} eq 'lti') && ($env{'request.lti.login'}) &&
+ ($env{'form.lti.reqrole'} eq 'cc') && ($env{'form.lti.reqcrs'}) &&
+ ($env{'form.lti.sourcecrs'} ne '')) {
+ if ($action eq 'process') {
+ if ($can_request{'lti'}) {
+ my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom);
+ &process_textbook_request($r,$dom,$action,\%domdefs,\%domconfig,\%can_request,'lti');
+ } else {
+ $r->print(&header('Course Request','','','',{ 'only_body' => 1}).
+ '<div>'.
+ '<p class="LC_info">'.&mt('You do not have privileges to request creation of LTI courses.').'</p>'.
+ '</div>'.
+ &Apache::loncommon::end_page());
+ }
+ }
+ return OK;
+ }
if (($env{'form.crstype'} eq 'textbook') ||
(scalar(keys(%can_request)) == 1) && ($can_request{'textbook'})) {
my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom);
@@ -192,7 +209,8 @@
}
} else {
if ($can_request{'textbook'}) {
- &print_textbook_form($r,$dom,\@incdoms,\%domdefs,$domconfig{'requestcourses'},\%can_request);
+ &print_textbook_form($r,$dom,\@incdoms,\%domdefs,$domconfig{'requestcourses'},
+ \%can_request,'textbook');
} else {
&textbook_request_disabled($r,$dom,$action,\%can_request);
}
@@ -4541,9 +4559,11 @@
}
sub print_textbook_form {
- my ($r,$dom,$incdoms,$domdefs,$settings,$can_request) = @_;
+ my ($r,$dom,$incdoms,$domdefs,$settings,$can_request,$crstype,$formhash) = @_;
my (%prefab,%ordered,%numprefab);
- my $crstype = 'textbook';
+ if ($crstype eq '') {
+ $crstype = 'textbook';
+ }
#
# Retrieve list of prefabricated courses (textbook courses and templates) cloneable by user
#
@@ -4660,31 +4680,37 @@
my $jscript = &textbook_request_javascript(\%numprefab,$numcurrent,$numdomcourses,$customvalidationjs);
$jscript .= $customjs;
- my %loaditems;
+ my (%loaditems,$args);
$loaditems{'onload'} = 'javascript:uncheckAllRadio();'.$customonload;
- $r->print(&header('Course Request',$jscript,\%loaditems));
+ if ($crstype eq 'lti') {
+ $args = { 'only_body' => 1};
+ }
+ $r->print(&header('Course Request',$jscript,\%loaditems,undef,$args));
if (ref($can_request) eq 'HASH') {
- unless ((scalar(keys(%{$can_request})) == 1) && ($can_request->{'textbook'})) {
+ unless (((scalar(keys(%{$can_request})) == 1) && ($can_request->{'textbook'})) ||
+ ($crstype eq 'lti')) {
&Apache::lonhtmlcommon::add_breadcrumb(
{ href => '/adm/requestcourse',
text => 'Pick action',
});
}
}
- &Apache::lonhtmlcommon::add_breadcrumb({text=>'Course Request'});
- $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests'));
+ unless ($crstype eq 'lti') {
+ &Apache::lonhtmlcommon::add_breadcrumb({text=>'Course Request'});
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests'));
- &startContentScreen($r,'textbookrequests');
+ &startContentScreen($r,'textbookrequests');
#
# Show domain selector form, if required.
#
- if (@{$incdoms} > 1) {
- my $onchange = 'this.form.submit()';
- $r->print('<form name="domforcourse" method="post" action="/adm/requestcourse">'.
- '<div><fieldset><legend>'.&mt('Domain').'</legend>'.
- &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange,$incdoms).
- '</fieldset></form>');
+ if (@{$incdoms} > 1) {
+ my $onchange = 'this.form.submit()';
+ $r->print('<form name="domforcourse" method="post" action="/adm/requestcourse">'.
+ '<div><fieldset><legend>'.&mt('Domain').'</legend>'.
+ &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange,$incdoms).
+ '</fieldset></form>');
+ }
}
#
@@ -4864,15 +4890,24 @@
#
# Submit button
#
- $r->print('<input type="hidden" name="crstype" value="textbook" />'.
+ $r->print('<input type="hidden" name="crstype" value="'.$crstype.'" />'.
'<input type="hidden" name="action" value="process" />'.
'<input type="submit" value="'.&mt('Create course').'" />');
#
# End request form
#
+
+ if (($crstype eq 'lti') && (ref($formhash) eq 'HASH')) {
+ foreach my $item (keys(%{$formhash})) {
+ $r->print('<input type="hidden" name="'.$item.'" value="'.$formhash->{$item}.'" />'."\n");
+ }
+ }
+
$r->print('</form>');
- &endContentScreen($r).
+ unless ($crstype eq 'lti') {
+ &endContentScreen($r);
+ }
$r->print(&Apache::loncommon::end_page());
return;
}
@@ -4959,9 +4994,11 @@
}
sub process_textbook_request {
- my ($r,$dom,$action,$domdefs,$domconfig,$can_request) = @_;
+ my ($r,$dom,$action,$domdefs,$domconfig,$can_request,$crstype) = @_;
my ($uniquecode,$req_notifylist);
- my $crstype = 'textbook';
+ if ($crstype eq '') {
+ $crstype = 'textbook';
+ }
if (ref($domconfig) eq 'HASH') {
if (ref($domconfig->{'requestcourses'}) eq 'HASH') {
if (ref($domconfig->{'requestcourses'}{'notify'}) eq 'HASH') {
@@ -5003,27 +5040,33 @@
}
}
my $js = &processing_javascript();
- my $loaditems = {
- onload => 'javascript:hideProcessing();',
- };
- $r->print(&header('Course Creation',$js,$loaditems));
-
- if (ref($can_request) eq 'HASH') {
- unless ((scalar(keys(%{$can_request})) == 1) && ($can_request->{'textbook'})) {
- &Apache::lonhtmlcommon::add_breadcrumb(
- { href => '/adm/requestcourse',
- text => 'Pick action',
- });
+ my ($loaditems,$args);
+ $loaditems = {
+ onload => 'javascript:hideProcessing();',
+ };
+ if ($crstype eq 'lti') {
+ $args = { 'only_body' => 1};
+ }
+ $r->print(&header('Course Creation',$js,$loaditems,undef,$args));
+
+ unless ($crstype eq 'lti') {
+ if (ref($can_request) eq 'HASH') {
+ unless ((scalar(keys(%{$can_request})) == 1) && ($can_request->{'textbook'})) {
+ &Apache::lonhtmlcommon::add_breadcrumb(
+ { href => '/adm/requestcourse',
+ text => 'Pick action',
+ });
+ }
}
+ &Apache::lonhtmlcommon::add_breadcrumb(
+ { href => '/adm/requestcourse',
+ text => "Create Course",
+ }
+ );
+ &Apache::lonhtmlcommon::add_breadcrumb({text=>'Request Processed'});
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests'));
+ &startContentScreen($r,'textbookrequests');
}
- &Apache::lonhtmlcommon::add_breadcrumb(
- { href => '/adm/requestcourse',
- text => "Create Course",
- }
- );
- &Apache::lonhtmlcommon::add_breadcrumb({text=>'Request Processed'});
- $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests'));
- &startContentScreen($r,'textbookrequests');
my $details = {
owner => $env{'user.name'},
@@ -5068,7 +5111,12 @@
my ($result,$output,$customized) = &process_request($r,$lonhost,$dom,$cnum,$crstype,$now,$details,
'',$req_notifylist,[],$domconfig);
$r->print($output);
- if (&Apache::loncoursequeueadmin::author_prompt()) {
+ if ($crstype eq 'lti') {
+ my %consumers = &Apache::lonnet::get_dom('lticonsumers',[$env{'form.sourcecrs'}],$dom);
+ if (($env{'form.lti.sourcecrs'} ne '') && ($consumers{$env{'form.lti.sourcecrs'}} eq '') && ($cnum ne '')) {
+ &Apache::lonnet::put_dom('lticonsumers',{ $env{'form.lti.sourcecrs'} => $cnum },$dom);
+ }
+ } elsif (&Apache::loncoursequeueadmin::author_prompt()) {
unless ($customized) {
&print_author_prompt($r,$action,$cnum,$dom,$crstype,$result);
}
@@ -5077,7 +5125,9 @@
$r->print('<p><a href="/adm/requestcourse">'.&mt('Create another course').'</a></p>');
}
}
- &endContentScreen($r);
+ unless ($crstype eq 'lti') {
+ &endContentScreen($r);
+ }
$r->print(&Apache::loncommon::end_page());
}
Index: loncom/interface/lonuserutils.pm
diff -u loncom/interface/lonuserutils.pm:1.193 loncom/interface/lonuserutils.pm:1.194
--- loncom/interface/lonuserutils.pm:1.193 Sat Nov 4 20:59:39 2017
+++ loncom/interface/lonuserutils.pm Fri Mar 23 01:01:21 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Utility functions for managing LON-CAPA user accounts
#
-# $Id: lonuserutils.pm,v 1.193 2017/11/04 20:59:39 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.194 2018/03/23 01:01:21 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -546,6 +546,7 @@
case 'fsys':
alertmsg = '';
break;
+ case 'lti':
default:
alertmsg = '';
}
@@ -898,6 +899,7 @@
my $krbform = &Apache::loncommon::authform_kerberos(%param);
my $intform = &Apache::loncommon::authform_internal(%param);
my $locform = &Apache::loncommon::authform_local(%param);
+ my $ltiform = &Apache::loncommon::authform_lti(%param);
my $date_table = &date_setting_table(undef,undef,$context,undef,
$formname,$permission,$crstype);
@@ -926,7 +928,7 @@
&Apache::loncommon::help_open_topic('Auth_Options').
"</p>\n";
}
- $Str .= &set_login($defdom,$krbform,$intform,$locform);
+ $Str .= &set_login($defdom,$krbform,$intform,$locform,$ltiform);
my ($home_server_pick,$numlib) =
&Apache::loncommon::home_server_form_item($defdom,'lcserver',
@@ -4251,6 +4253,8 @@
if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
$genpwd=$env{'form.locarg'};
}
+ } elsif ($env{'form.login'} eq 'lti') {
+ $amode='lti';
}
if ($amode =~ /^krb/) {
if (! defined($genpwd) || $genpwd eq '') {
@@ -4625,7 +4629,7 @@
&mt('The user does not already exist, and you may not create a new user in a different domain.');
next;
} else {
- unless ($password || $env{'form.login'} eq 'loc') {
+ unless (($password ne '') || ($env{'form.login'} eq 'loc') || ($env{'form.login'} eq 'lti')) {
$disallow{$counter} =
&mt('[_1]: This is a new user but no default password was provided, and the authentication type requires one.',
'<b>'.$username.'</b>');
@@ -5491,7 +5495,7 @@
}
sub set_login {
- my ($dom,$authformkrb,$authformint,$authformloc) = @_;
+ my ($dom,$authformkrb,$authformint,$authformloc,$authformlti) = @_;
my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
my $response;
my ($authnum,%can_assign) =
@@ -5513,6 +5517,11 @@
'<td>'.$authformloc.'</td>'.
&Apache::loncommon::end_data_table_row()."\n";
}
+ if ($can_assign{'lti'}) {
+ $response .= &Apache::loncommon::start_data_table_row().
+ '<td>'.$authformlti.'</td>'.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
$response .= &Apache::loncommon::end_data_table();
}
return $response;
Index: loncom/auth/lonauth.pm
diff -u loncom/auth/lonauth.pm:1.148 loncom/auth/lonauth.pm:1.149
--- loncom/auth/lonauth.pm:1.148 Tue Aug 8 18:26:34 2017
+++ loncom/auth/lonauth.pm Fri Mar 23 01:01:29 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network
# User Authentication Module
#
-# $Id: lonauth.pm,v 1.148 2017/08/08 18:26:34 raeburn Exp $
+# $Id: lonauth.pm,v 1.149 2018/03/23 01:01:29 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -36,6 +36,7 @@
use Apache::lonnet;
use Apache::lonmenu();
use Apache::createaccount;
+use Apache::ltiauth;
use Fcntl qw(:flock);
use Apache::lonlocal;
use Apache::File();
@@ -45,7 +46,7 @@
# ------------------------------------------------------------ Successful login
sub success {
my ($r, $username, $domain, $authhost, $lowerurl, $extra_env,
- $form) = @_;
+ $form,$skipcritical) = @_;
# ------------------------------------------------------------ Get cookie ready
my $cookie =
@@ -64,10 +65,12 @@
# ------------------------------------------------- Check for critical messages
- my @what=&Apache::lonnet::dump('critical',$domain,$username);
- if ($what[0]) {
- if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) {
- $lowerurl='/adm/email?critical=display';
+ unless ($skipcritical) {
+ my @what=&Apache::lonnet::dump('critical',$domain,$username);
+ if ($what[0]) {
+ if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) {
+ $lowerurl='/adm/email?critical=display';
+ }
}
}
@@ -93,7 +96,29 @@
}
# -------------------------------------------------------- Menu script and info
my $destination = $lowerurl;
-
+ if ($env{'request.lti.login'}) {
+ if (($env{'request.lti.reqcrs'}) && ($env{'request.lti.reqrole'} eq 'cc')) {
+ &Apache::loncommon::content_type($r,'text/html');
+ if ($securecookie) {
+ $r->headers_out->add('Set-cookie' => $securecookie);
+ }
+ if ($defaultcookie) {
+ $r->headers_out->add('Set-cookie' => $defaultcookie);
+ }
+ $r->send_http_header;
+ &Apache::ltiauth::lti_reqcrs($r,$domain,$form,$username,$domain);
+ return;
+ }
+ if ($env{'request.lti.selfenrollrole'}) {
+ if (&Apache::ltiauth::lti_enroll($username,$domain,
+ $env{'request.lti.selfenrollrole'}) eq 'ok') {
+ $form->{'role'} = $env{'request.lti.selfenrollrole'};
+ &Apache::lonnet::delenv('request.lti.selfenrollrole');
+ } else {
+ &Apache::ltiauth::invalid_request($r,24);
+ }
+ }
+ }
if (defined($form->{role})) {
my $envkey = 'user.role.'.$form->{role};
my $now=time;
@@ -161,11 +186,7 @@
}
}
}
- my $start_page=&Apache::loncommon::start_page('Successful Login',
- $header,$args);
- my $end_page =&Apache::loncommon::end_page();
- my $continuelink='<a href="'.$destination.'">'.&mt('Continue').'</a>';
# ------------------------------------------------- Output for successful login
&Apache::loncommon::content_type($r,'text/html');
@@ -177,6 +198,12 @@
}
$r->send_http_header;
+ my $start_page=&Apache::loncommon::start_page('Successful Login',
+ $header,$args);
+ my $end_page =&Apache::loncommon::end_page();
+
+ my $continuelink='<a href="'.$destination.'">'.&mt('Continue').'</a>';
+
my %lt=&Apache::lonlocal::texthash(
'wel' => 'Welcome',
'pro' => 'Login problems?',
@@ -407,7 +434,7 @@
my $authhost=Apache::lonnet::authenticate($form{'uname'},$upass,
$form{'udom'},$defaultauth,
$clientcancheckhost);
-
+
# --------------------------------------------------------------------- Failed?
if ($authhost eq 'no_host') {
Index: loncom/auth/migrateuser.pm
diff -u loncom/auth/migrateuser.pm:1.26 loncom/auth/migrateuser.pm:1.27
--- loncom/auth/migrateuser.pm:1.26 Thu Nov 30 15:14:51 2017
+++ loncom/auth/migrateuser.pm Fri Mar 23 01:01:29 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Starts a user off based of an existing token.
#
-# $Id: migrateuser.pm,v 1.26 2017/11/30 15:14:51 raeburn Exp $
+# $Id: migrateuser.pm,v 1.27 2018/03/23 01:01:29 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -35,25 +35,29 @@
use Apache::lonnet;
use Apache::lonlocal;
use Apache::lonlogin();
+use Apache::ltiauth;
sub goto_login {
- my ($r,$domain) = @_;
- &Apache::loncommon::content_type($r,'text/html');
- $r->send_http_header;
- my $url = '/adm/login';
- if ($domain) {
- $url .= '?domain='.$domain;
- }
- $r->print(&Apache::loncommon::start_page('Going to login',undef,
- {'redirect' => [0,$url],}).
- '<h1>'.&mt('One moment please...').'</h1>'.
- '<p>'.&mt('Transferring to login page.').'</p>'.
- &Apache::loncommon::end_page());
+ my ($r,$domain,$data) = @_;
+ if ((ref($data) eq 'HASH') && ($data->{'lti.login'})) {
+ &Apache::ltiauth::invalid_request($r,'22');
+ } else {
+ &Apache::loncommon::content_type($r,'text/html');
+ $r->send_http_header;
+ my $url = '/adm/login';
+ if ($domain) {
+ $url .= '?domain='.$domain;
+ }
+ $r->print(&Apache::loncommon::start_page('Going to login',undef,
+ {'redirect' => [0,$url],}).
+ '<h1>'.&mt('One moment please...').'</h1>'.
+ '<p>'.&mt('Transferring to login page.').'</p>'.
+ &Apache::loncommon::end_page());
+ }
return OK;
}
-
-sub sso_lti_check {
+sub sso_check {
my ($data) = @_;
my %extra_env;
if (ref($data) eq 'HASH') {
@@ -64,23 +68,40 @@
$extra_env{'request.sso.reloginserver'} =
$data->{'sso.reloginserver'};
}
+ }
+ return \%extra_env;
+}
+
+sub lti_check {
+ my ($data) = @_;
+ my %lti_env;
+ if (ref($data) eq 'HASH') {
if ($data->{'lti.login'}) {
- $extra_env{'request.lti.login'} = $data->{'lti.login'};
+ $lti_env{'request.lti.login'} = $data->{'lti.login'};
+ if ($data->{'lti.reqcrs'}) {
+ $lti_env{'request.lti.reqcrs'} = $data->{'lti.reqcrs'};
+ }
+ if ($data->{'lti.reqrole'}) {
+ $lti_env{'request.lti.reqrole'} = $data->{'lti.reqrole'};
+ }
+ if ($data->{'lti.selfenrollrole'}) {
+ $lti_env{'request.lti.selfenrollrole'} = $data->{'lti.selfenrollrole'};
+ }
}
if ($data->{'lti.passbackid'}) {
- $extra_env{'request.lti.passbackid'} = $data->{'lti.passbackid'};
+ $lti_env{'request.lti.passbackid'} = $data->{'lti.passbackid'};
}
if ($data->{'lti.passbackurl'}) {
- $extra_env{'request.lti.passbackurl'} = $data->{'lti.passbackurl'};
+ $lti_env{'request.lti.passbackurl'} = $data->{'lti.passbackurl'};
}
if ($data->{'lti.rosterid'}) {
- $extra_env{'request.lti.rosterid'} = $data->{'lti.rosterid'};
+ $lti_env{'request.lti.rosterid'} = $data->{'lti.rosterid'};
}
if ($data->{'lti.rosterurl'}) {
- $extra_env{'request.lti.rosterurl'} = $data->{'lti.rosterurl'};
+ $lti_env{'request.lti.rosterurl'} = $data->{'lti.rosterurl'};
}
}
- return \%extra_env;
+ return \%lti_env;
}
sub ip_changed {
@@ -238,11 +259,11 @@
&Apache::lonlocal::get_language_handle($r);
if ($delete ne 'ok') {
- return &goto_login($r);
+ return &goto_login($r,undef,\%data);
}
if (!defined($data{'username'}) || !defined($data{'domain'})) {
- return &goto_login($r);
+ return &goto_login($r,undef,\%data);
}
if ($data{'ip'} ne $ENV{'REMOTE_ADDR'}) {
&Apache::lonnet::logthis('IP change when session migration requested -- was: '.
@@ -256,9 +277,17 @@
if (&Apache::lonnet::domain($data{'domain'})) {
$udom=$data{'domain'};
}
- if ($home =~ /(con_lost|no_such_host)/) { return &goto_login($r,$udom); }
+ if ($home =~ /(con_lost|no_such_host)/) { return &goto_login($r,$udom,\%data); }
+
+ my $sso_env = &sso_check(\%data);
+ my $lti_env = <i_check(\%data);
- my $extra_env = &sso_lti_check(\%data);
+ my $extra_env;
+ if ((ref($sso_env) eq 'HASH') && (keys(%{$sso_env}))) {
+ $extra_env = $sso_env;
+ } elsif ((ref($lti_env) eq 'HASH') && (keys(%{$lti_env}))) {
+ $extra_env = $lti_env;
+ }
my %form;
if ($data{'symb'} ne '') {
@@ -276,7 +305,37 @@
if ($handle) {
&Apache::lonnet::transfer_profile_to_env($r->dir_config('lonIDsDir'),
$handle);
- if ($data{'origurl'} ne '') {
+#FIXME if user is not currently logged in as an LTI log-in log them out.
+ if ($data{'lti.login'}) {
+ if (($data{'lti.reqcrs'}) && ($data{'lti.reqrole'} eq 'cc')) {
+ $form{'lti.reqcrs'} = $data{'lti.reqcrs'};
+ $form{'lti.reqrole'} = $data{'lti.reqrole'};
+ $form{'lti.sourcecrs'} = $data{'lti.sourcecrs'};
+ &Apache::loncommon::content_type($r,'text/html');
+ $r->send_http_header;
+ &Apache::ltiauth::lti_reqcrs($r,$data{'domain'},\%form,$data{'username'},$data{'domain'});
+ } elsif ($data{'lti.selfenrollrole'}) {
+ if (&Apache::ltiauth::lti_enroll($data{'username'},data{'domain'},
+ $data{'lti.selfenrollrole'}) eq 'ok') {
+ my $url = '/adm/roles?selectrole=1&'.
+ &escape($data{'lti.selfenrollrole'}).'=1';
+ if ($data{'origurl'} =~ m{/default_\d+\.sequence$}) {
+ $url .= '&orgurl='.$data{'origurl'}.'&navmap=1';
+ } elsif ($data{'origurl'} ne '') {
+ $url .= '&orgurl='.$data{'origurl'};
+ }
+ $r->internal_redirect($url);
+ } else {
+ &Apache::ltiauth::invalid_request($r,23);
+ }
+ } elsif ($data{'origurl'} ne '') {
+ my $url = $data{'origurl'};
+ if ($url =~ m{/default_\d+\.sequence$}) {
+ $url .= (($url =~/\?/)?'&':'?').'navmap=1';
+ }
+ $r->internal_redirect($url);
+ }
+ } elsif ($data{'origurl'} ne '') {
$r->internal_redirect($data{'origurl'});
} elsif ($env{'request.course.id'}) {
$r->internal_redirect('/adm/navmaps');
@@ -287,13 +346,22 @@
my $desturl = '/adm/roles';
if ($data{'origurl'} ne '') {
$desturl = $data{'origurl'};
+ if ($data{'lti.login'}) {
+ $desturl = $data{'origurl'};
+ if ($desturl =~ m{/default_\d+\.sequence$}) {
+ $desturl .= (($desturl =~/\?/)?'&':'?').'navmap=1';
+ }
+ }
+ }
+ my $skipcritical;
+ if (($data{'lti.login'}) && ($data{'lti.reqcrs'}) &&
+ ($data{'lti.reqrole'} eq 'cc')) {
+ $skipcritical = 1;
}
&Apache::lonauth::success($r,$data{'username'},$data{'domain'},
- $home,$desturl,$extra_env,\%form);
-
+ $home,$desturl,$extra_env,\%form,$skipcritical);
}
return OK;
-
}
my $next_url='/adm/roles?selectrole=1&'.&escape($data{'role'}).'=1';
Index: loncom/auth/switchserver.pm
diff -u loncom/auth/switchserver.pm:1.38 loncom/auth/switchserver.pm:1.39
--- loncom/auth/switchserver.pm:1.38 Thu Nov 30 15:14:51 2017
+++ loncom/auth/switchserver.pm Fri Mar 23 01:01:29 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Switch Servers Handler
#
-# $Id: switchserver.pm,v 1.38 2017/11/30 15:14:51 raeburn Exp $
+# $Id: switchserver.pm,v 1.39 2018/03/23 01:01:29 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -180,6 +180,10 @@
my $logmsg = "Switch Server to $env{'form.otherserver'}";
if ($env{'form.role'}) {
$logmsg .= " with role: $env{'form.role'}";
+ } elsif (($env{'form.lti.reqcrs'}) && ($env{'form.lti.reqrole'} eq 'cc')) {
+ $logmsg .= " to create new LTI course";
+ } elsif ($env{'form.lti.selfenrollrole'}) {
+ $logmsg .= " to selfenroll with role: $env{'form.lti.selfenrollrole'}";
} else {
$logmsg .= " (no role)";
}
@@ -231,6 +235,18 @@
if ($env{'request.lti.login'}) {
$info{'lti.login'} = $env{'request.lti.login'};
}
+ if ($env{'request.lti.reqcrs'}) {
+ $info{'lti.reqcrs'} = $env{'request.lti.reqcrs'};
+ }
+ if ($env{'request.lti.reqrole'}) {
+ $info{'lti.reqrole'} = $env{'request.lti.reqrole'};
+ }
+ if ($env{'request.lti.selfenrollrole'}) {
+ $info{'lti.selfenrollrole'} = $env{'request.lti.selfenrollrole'};
+ }
+ if ($env{'request.lti.sourcecrs'}) {
+ $info{'lti.sourcecrs'} = $env{'request.lti.sourcecrs'};
+ }
if ($env{'request.lti.passbackid'}) {
$info{'lti.passbackid'} = $env{'request.lti.passbackid'};
}
Index: loncom/lti/ltiauth.pm
diff -u loncom/lti/ltiauth.pm:1.5 loncom/lti/ltiauth.pm:1.6
--- loncom/lti/ltiauth.pm:1.5 Fri Jan 12 20:42:38 2018
+++ loncom/lti/ltiauth.pm Fri Mar 23 01:01:47 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Basic LTI Authentication Module
#
-# $Id: ltiauth.pm,v 1.5 2018/01/12 20:42:38 raeburn Exp $
+# $Id: ltiauth.pm,v 1.6 2018/03/23 01:01:47 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -36,6 +36,7 @@
use Apache::lonnet;
use Apache::loncommon;
use Apache::lonacc;
+use Apache::lonrequestcourse;
use LONCAPA::ltiutils;
sub handler {
@@ -181,7 +182,6 @@
$symb = $tail;
$symb =~ s{^/+}{};
}
-#FIXME Need to handle encrypted URLs
} elsif ($tail =~ m{^/($match_domain)/($match_courseid)$}) {
($urlcdom,$urlcnum) = ($1,$2);
if (($cdom ne '') && ($cdom ne $urlcdom)) {
@@ -262,7 +262,7 @@
$protocol = 'https';
}
- my ($itemid,$consumer_key,$secret, at ltiroles);
+ my ($itemid,$consumer_key,$secret);
$consumer_key = $params->{'oauth_consumer_key'};
if (ref($lti_by_key{$consumer_key}) eq 'ARRAY') {
foreach my $id (@{$lti_by_key{$consumer_key}}) {
@@ -301,7 +301,7 @@
}
#
-# Determinine if source of username matches requirement from the
+# Determine if source of username matches requirement from the
# domain configuration for the specific LTI Consumer.
#
@@ -387,39 +387,40 @@
}
#
-# Get LON-CAPA role to use from role-mapping of Consumer roles
+# Get LON-CAPA role(s) to use from role-mapping of Consumer roles
# defined in domain configuration for the appropriate LTI
# Consumer.
#
-# If multiple LON-CAPA roles are indicated, choose based
-# on the order: cc, in, ta, ep, st
+# If multiple LON-CAPA roles are indicated for the current user,
+# ordering (from first to last) is: cc/co, in, ta, ep, st.
#
- my $reqrole;
+ my (@ltiroles, at lcroles);
- my @roleorder = ('cc','in','ta','ep','st');
+ my @lcroleorder = ('cc','in','ta','ep','st');
+ my @ltiroleorder = ('Instructor','TeachingAssistant','Mentor','Learner');
if ($params->{'roles'} =~ /,/) {
- @ltiroles = split(/\s*,\s*/,$params->{'role'});
+ my @possltiroles = split(/\s*,\s*/,$params->{'role'});
+ foreach my $ltirole (@ltiroleorder) {
+ if (grep(/^\Q$ltirole\E$/, at possltiroles)) {
+ push(@ltiroles,$ltirole);
+ }
+ }
} else {
my $singlerole = $params->{'roles'};
$singlerole =~ s/^\s|\s+$//g;
- @ltiroles = ($singlerole);
+ if (grep(/^\Q$singlerole\E$/, at ltiroleorder)) {
+ @ltiroles = ($singlerole);
+ }
}
if (@ltiroles) {
if (ref($lti{$itemid}{maproles}) eq 'HASH') {
my %possroles;
map { $possroles{$lti{$itemid}{maproles}{$_}} = 1; } @ltiroles;
- my @possibles = keys(%possroles);
- if (@possibles == 1) {
- if (grep(/^\Q$possibles[0]\E$/, at roleorder)) {
- $reqrole = $possibles[0];
-
- }
- } elsif (@possibles > 1) {
- foreach my $item (@roleorder) {
+ if (keys(%possroles) > 0) {
+ foreach my $item (@lcroleorder) {
if ($possroles{$item}) {
- $reqrole = $item;
- last;
+ push(@lcroles,$item);
}
}
}
@@ -440,38 +441,148 @@
foreach my $ltirole (@ltiroles) {
if (grep(/^\Q$ltirole\E$/,@{$lti{$itemid}{'makeuser'}})) {
$selfcreate = 1;
+ last;
}
}
}
}
if ($selfcreate) {
-#FIXME Do user creation here.
- return OK
+ my (%rulematch,%inst_results,%curr_rules,%got_rules,%alerts,%info);
+ my $checkhash = { "$uname:$udom" => { 'newuser' => 1, }, };
+ my $checks = { 'username' => 1, };
+ &Apache::loncommon::user_rule_check($checkhash,$checks,\%alerts,\%rulematch,
+ \%inst_results,\%curr_rules,\%got_rules);
+ my ($userchkmsg,$lcauth,$lcauthparm);
+ my $allowed = 1;
+ if (ref($alerts{'username'}) eq 'HASH') {
+ if (ref($alerts{'username'}{$udom}) eq 'HASH') {
+ my $domdesc =
+ &Apache::lonnet::domain($udom,'description');
+ if ($alerts{'username'}{$udom}{$uname}) {
+ if (ref($curr_rules{$udom}) eq 'HASH') {
+ $userchkmsg =
+ &Apache::loncommon::instrule_disallow_msg('username',$domdesc,1).
+ &Apache::loncommon::user_rule_formats($udom,$domdesc,
+ $curr_rules{$udom}{'username'},
+ 'username');
+ }
+ $allowed = 0;
+ }
+ }
+ }
+ if ($allowed) {
+ if (ref($rulematch{$uname.':'.$udom}) eq 'HASH') {
+ my $matchedrule = $rulematch{$uname.':'.$udom}{'username'};
+ my ($rules,$ruleorder) =
+ &Apache::lonnet::inst_userrules($udom,'username');
+ if (ref($rules) eq 'HASH') {
+ if (ref($rules->{$matchedrule}) eq 'HASH') {
+ $lcauth = $rules->{$matchedrule}{'authtype'};
+ $lcauthparm = $rules->{$matchedrule}{'authparm'};
+ }
+ }
+ }
+ if ($lcauth eq '') {
+ $lcauth = $lti{$itemid}{'lcauth'};
+ $lcauthparm = $lti{$itemid}{'lcauthparm'};
+ }
+ } else {
+ &invalid_request($r,12);
+ }
+ my @userinfo = ('firstname','middlename','lastname','generation',
+ 'permanentemail','id');
+ my %useinstdata;
+ if (ref($lti{$itemid}{'instdata'}) eq 'ARRAY') {
+ map { $useinstdata{$_} = 1; } @{$lti{$itemid}{'instdata'}};
+ }
+ foreach my $item (@userinfo) {
+ if (($useinstdata{$item}) && (ref($inst_results{$uname.':'.$udom}) eq 'HASH') &&
+ ($inst_results{$uname.':'.$udom}{$item} ne '')) {
+ $info{$item} = $inst_results{$uname.':'.$udom}{$item};
+ } else {
+ if ($item eq 'permanentemail') {
+ if ($env{'form.lis_person_contact_email_primary'} =~/^[^\@]+\@[^@]+$/) {
+ $info{$item} = $env{'form.lis_person_contact_email_primary'};
+ }
+ } elsif ($item eq 'firstname') {
+ $info{$item} = $env{'form.lis_person_name_given'};
+ } elsif ($item eq 'lastname') {
+ $info{$item} = $env{'form.lis_person_name_family'};
+ }
+ }
+ }
+ if (($info{'middlename'} eq '') && ($env{'form.lis_person_name_full'} ne '')) {
+ unless ($useinstdata{'middlename'}) {
+ my $fullname = $env{'form.lis_person_name_full'};
+ if ($info{'firstname'}) {
+ $fullname =~ s/^\s*\Q$info{'firstname'}\E\s*//i;
+ }
+ if ($info{'lastname'}) {
+ $fullname =~ s/\s*\Q$info{'lastname'}\E\s*$//i;
+ }
+ if ($fullname ne '') {
+ $fullname =~ s/^\s+|\s+$//g;
+ if ($fullname ne '') {
+ $info{'middlename'} = $fullname;
+ }
+ }
+ }
+ }
+ if (ref($inst_results{$uname.':'.$udom}{'inststatus'}) eq 'ARRAY') {
+ my @inststatuses = @{$inst_results{$uname.':'.$udom}{'inststatus'}};
+ $info{'inststatus'} = join(':',map { &escape($_); } @inststatuses);
+ }
+ my $result =
+ &Apache::lonnet::modifyuser($udom,$uname,$info{'id'},
+ $lcauth,$lcauthparm,$info{'firstname'},
+ $info{'middlename'},$info{'lastname'},
+ $info{'generation'},undef,undef,
+ $info{'permanentemail'},$info{'inststatus'});
+ if ($result eq 'ok') {
+ if (($ltiroles[0] eq 'Instructor') && ($lcroles[0] eq 'cc') && ($lti{$itemid}{'mapcrs'}) &&
+ ($lti{$itemid}{'makecrs'})) {
+ unless (&Apache::lonnet::usertools_access($uname,$udom,'lti','reload','requestcourses')) {
+ &Apache::lonnet::put('environment',{ 'requestcourses.lti' => 1, },$udom,$uname);
+ }
+ }
+ } else {
+ &invalid_request($r,13);
+ return OK;
+ }
} else {
- &invalid_request($r,12);
+ &invalid_request($r,14);
return OK;
- }
- }
+ }
+ }
} else {
- &invalid_request($r,13);
+ &invalid_request($r,15);
return OK;
}
#
# If no LON-CAPA course available, check if domain's configuration
# for the specific LTI Consumer allows a new course to be created
-# (requires role in Consumer to be: Instructor).
+# (requires role in Consumer to be: Instructor and Instructor to map to CC)
#
+ my $reqcrs;
if ($cnum eq '') {
- if ((@ltiroles) && (grep(/^Instructor$/, at ltiroles)) &&
- ($lti{$itemid}{'mapcrs'})) {
-#FIXME Create a new LON-CAPA course here.
- return OK;
+ if ((@ltiroles) && ($lti{$itemid}{'mapcrs'}) &&
+ ($ltiroles[0] eq 'Instructor') && ($lcroles[0] eq 'cc') && ($lti{$itemid}{'makecrs'})) {
+ my (%can_request,%request_domains);
+ &Apache::lonnet::check_can_request($cdom,\%can_request,\%request_domains,$uname,$udom);
+ if ($can_request{'lti'}) {
+ $reqcrs = 1;
+ <i_session($r,$itemid,$uname,$udom,$uhome,$lonhost,undef,$mapurl,$tail,
+ $symb,$cdom,$cnum,$params,\@ltiroles,$lti{$itemid},\@lcroles,
+ $reqcrs,$sourcecrs);
+ } else {
+ &invalid_request($r,16);
+ }
} else {
- &invalid_request($r,14);
- return OK;
+ &invalid_request($r,17);
}
+ return OK;
}
#
@@ -479,48 +590,204 @@
# indicated is cc, change role indicated to co.
#
- if ($reqrole eq 'cc') {
+ my %crsenv;
+ if ($lcroles[0] eq 'cc') {
if (($cdom ne '') && ($cnum ne '')) {
- my %crsenv = &Apache::lonnet::coursedescription($cnum.'_'.$cdom,{ 'one_time' => 1,});
+ %crsenv = &Apache::lonnet::coursedescription($cdom.'_'.$cnum,{ 'one_time' => 1,});
if ($crsenv{'type'} eq 'Community') {
- $reqrole = 'co';
+ $lcroles[0] = 'co';
+ }
+ }
+ }
+
+#
+# Determine if user has a LON-CAPA role in the mapped LON-CAPA course.
+# If multiple LON-CAPA roles are available for the user's assigned LTI roles,
+# choose the first available LON-CAPA role in the order: cc/co, in, ta, ep, st
+#
+
+ my ($role,$usec,$withsec);
+ unless ((($lcroles[0] eq 'cc') || ($lcroles[0] eq 'co')) && (@lcroles == 1)) {
+ if ($lti{$itemid}{'section'} ne '') {
+ if ($lti{$itemid}{'section'} eq 'course_section_sourcedid') {
+ if ($env{'form.course_section_sourcedid'} !~ /\W/) {
+ $usec = $env{'form.course_section_sourcedid'};
+ }
+ } elsif ($env{'form.'.$lti{$itemid}{'section'}} !~ /\W/) {
+ $usec = $env{'form.'.$lti{$itemid}{'section'}};
+ }
+ }
+ if ($usec ne '') {
+ $withsec = 1;
+ }
+ }
+
+ if (@lcroles) {
+ my %crsroles = &Apache::lonnet::get_my_roles($uname,$udom,'userroles',undef,\@lcroles,
+ [$cdom],$withsec);
+ foreach my $reqrole (@lcroles) {
+ if ($withsec) {
+ my $incsec;
+ if (($reqrole eq 'cc') || ($reqrole eq 'co')) {
+ $incsec = '';
+ } else {
+ $incsec = $usec;
+ }
+ if (exists($crsroles{$cnum.':'.$cdom.':'.$reqrole.':'.$incsec})) {
+ $role = $reqrole.'./'.$cdom.'/'.$cnum;
+ if ($incsec ne '') {
+ $role .= '/'.$usec;
+ }
+ last;
+ }
+ } else {
+ if (exists($crsroles{$cnum.':'.$cdom.':'.$reqrole})) {
+ $role = $reqrole.'./'.$cdom.'/'.$cnum;
+ last;
+ }
}
}
}
#
-# Determine if user has required LON-CAPA role
-# in the mapped LON-CAPA course.
+# Determine if user can selfenroll
#
- my $role;
- my %crsroles = &Apache::lonnet::get_my_roles($uname,$udom,'userroles',undef,[$reqrole],[$cdom]);
- if (exists($crsroles{$cnum.':'.$cdom.':'.$reqrole})) {
- $role = $reqrole.'./'.$cdom.'/'.$cnum;
-#FIXME Need to accommodate sections
- } elsif (ref($lti{$itemid}{'selfenroll'}) eq 'ARRAY') {
- if (grep(/^\Q$reqrole\E$/,@{$lti{$itemid}{'selfenroll'}})) {
-#FIXME Do self-enrollment here
+ my ($reqrole,$selfenrollrole);
+ if ($role eq '') {
+ if ((@ltiroles) && (ref($lti{$itemid}{'selfenroll'}) eq 'ARRAY')) {
+ foreach my $ltirole (@ltiroles) {
+ if (grep(/^\Q$ltirole\E$/,@{$lti{$itemid}{'selfenroll'}})) {
+ if (ref($lti{$itemid}{maproles}) eq 'HASH') {
+ $reqrole = $lti{$itemid}{maproles}{$ltirole};
+ last;
+ }
+ }
+ }
+ }
+ if ($reqrole eq '') {
+ &invalid_request($r,18);
return OK;
} else {
- &invalid_request($r,15);
- return OK;
+ unless (%crsenv) {
+ %crsenv = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+ }
+ my $default_enrollment_start_date = $crsenv{'default_enrollment_start_date'};
+ my $default_enrollment_end_date = $crsenv{'default_enrollment_end_date'};
+ my $now = time;
+ if ($default_enrollment_end_date && $default_enrollment_end_date <= $now) {
+ &invalid_request($r,19);
+ return OK;
+ } elsif ($default_enrollment_start_date && $default_enrollment_start_date >$now) {
+ &invalid_request($r,20);
+ return OK;
+ } else {
+ $selfenrollrole = $reqrole.'./'.$cdom.'/'.$cnum;
+ if (($withsec) && ($reqrole ne 'cc') && ($reqrole ne 'co')) {
+ if ($usec ne '') {
+ $selfenrollrole .= '/'.$usec;
+ }
+ }
+ }
}
}
#
# Store consumer-to-LON-CAPA course mapping
#
+
if (($sourcecrs ne '') && ($consumers{$sourcecrs} eq '') && ($cnum ne '')) {
&Apache::lonnet::put_dom('lticonsumers',{ $sourcecrs => $cnum },$cdom);
}
#
-# Check if user should be hosted here or switched to another server.
+# Start user session
#
- &Apache::lonnet::logthis(" LTI authorized user: $uname:$udom role: $role course: $cdom\_$cnum");
+ <i_session($r,$itemid,$uname,$udom,$uhome,$lonhost,$role,$mapurl,$tail,$symb,
+ $cdom,$cnum,$params,\@ltiroles,$lti{$itemid},\@lcroles,undef,$sourcecrs,
+ $selfenrollrole);
+ return OK;
+}
+
+sub lti_enroll {
+ my ($uname,$udom,$selfenrollrole) = @_;
+ my $enrollresult;
+ my ($role,$cdom,$cnum,$sec) =
+ ($selfenrollrole =~ m{^(\w+)\./($match_domain)/($match_courseid)(?:|/(\w*))$});
+ if (($cnum ne '') && ($cdom ne '')) {
+ my $chome = &Apache::lonnet::homeserver($cnum,$cdom);
+ if ($chome ne 'no_host') {
+ my %coursehash = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+ my $start = $coursehash{'default_enrollment_start_date'};
+ my $end = $coursehash{'default_enrollment_end_date'};
+ my $area = "/$cdom/$cnum";
+ if (($role ne 'cc') && ($role ne 'co') && ($sec ne '')) {
+ $area .= '/'.$sec;
+ }
+ my $spec = $role.'.'.$area;
+ my $instcid;
+ if ($role eq 'st') {
+ $enrollresult =
+ &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,
+ undef,undef,$sec,$end,$start,
+ 'ltienroll',undef,$cdom.'_'.$cnum,1,
+ 'ltienroll','',$instcid);
+ } elsif ($role =~ /^(cc|in|ta|ep)$/) {
+ $enrollresult =
+ &Apache::lonnet::assignrole($udom,$uname,$area,$role,$end,$start,
+ undef,1,'ltienroll');
+ }
+ if ($enrollresult eq 'ok') {
+ my (%userroles,%newrole,%newgroups);
+ &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum,
+ $area);
+ &Apache::lonnet::set_userprivs(\%userroles,\%newrole,\%newgroups);
+ $userroles{'user.role.'.$spec} = $start.'.'.$end;
+ &Apache::lonnet::appenv(\%userroles,[$role,'cm']);
+ }
+ }
+ }
+ return $enrollresult;
+}
+
+sub lti_reqcrs {
+ my ($r,$cdom,$form,$uname,$udom) = @_;
+ my (%can_request,%request_domains);
+ &Apache::lonnet::check_can_request($cdom,\%can_request,\%request_domains,$uname,$udom);
+ if ($can_request{'lti'}) {
+ my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$cdom);
+ my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
+ &Apache::lonrequestcourse::print_textbook_form($r,$cdom,[$cdom],\%domdefs,
+ $domconfig{'requestcourses'},
+ \%can_request,'lti',$form);
+ } else {
+ $r->print(
+ &Apache::loncommon::start_page('Invalid LTI call',undef,{'only_body' => 1}).
+ &mt('Invalid LTI call').
+ &Apache::loncommon::end_page()
+ );
+ }
+}
+
+sub lti_session {
+ my ($r,$itemid,$uname,$udom,$uhome,$lonhost,$role,$mapurl,$tail,$symb,$cdom,$cnum,
+ $params,$ltiroles,$ltihash,$lcroles,$reqcrs,$sourcecrs,$selfenrollrole) = @_;
+ return unless ((ref($params) eq 'HASH') && (ref($ltiroles) eq 'ARRAY') &&
+ (ref($ltihash) eq 'HASH') && (ref($lcroles) eq 'ARRAY'));
+#
+# Check if user should be hosted here or switched to another server.
+#
$r->user($uname);
+ if ($cnum) {
+ if ($role) {
+ &Apache::lonnet::logthis(" LTI authorized user ($itemid): $uname:$udom, role: $role, course: $cdom\_$cnum");
+ } elsif ($selfenrollrole =~ m{^(\w+)\./$cdom/$cnum}) {
+ &Apache::lonnet::logthis(" LTI authorized user ($itemid): $uname:$udom, desired role: $1 course: $cdom\_$cnum");
+ }
+ } else {
+ &Apache::lonnet::logthis(" LTI authorized user ($itemid): $uname:$udom, course dom: $cdom");
+ }
my ($is_balancer,$otherserver,$hosthere);
($is_balancer,$otherserver) =
&Apache::lonnet::check_loadbalancing($uname,$udom,'login');
@@ -544,11 +811,30 @@
&Apache::lonauth::success($r,$uname,$udom,$uhome,'noredirect');
if ($symb) {
$env{'form.symb'} = $symb;
+ } else {
+ if ($mapurl) {
+ $env{'form.origurl'} = $mapurl;
+ } elsif ($tail =~ m{^\Q/tiny/$cdom/\E\w+$}) {
+ $env{'form.origurl'} = $tail;
+ } else {
+ unless ($tail eq '/adm/roles') {
+ $env{'form.origurl'} = '/adm/navmaps';
+ }
+ }
}
if ($role) {
$env{'form.role'} = $role;
}
- if ($lti{$itemid}{'passback'}) {
+ if (($lcroles->[0] eq 'cc') && ($reqcrs)) {
+ $env{'request.lti.reqcrs'} = 1;
+ $env{'request.lti.reqrole'} = 'cc';
+ $env{'request.lti.sourcecrs'} = $sourcecrs;
+ }
+ if ($selfenrollrole) {
+ $env{'request.lti.selfenroll'} = $selfenrollrole;
+ $env{'request.lti.sourcecrs'} = $sourcecrs;
+ }
+ if ($ltihash->{'passback'}) {
if ($params->{'lis_result_sourcedid'}) {
$env{'request.lti.passbackid'} = $params->{'lis_result_sourcedid'};
}
@@ -556,9 +842,9 @@
$env{'request.lti.passbackurl'} = $params->{'lis_outcome_service_url'};
}
}
- if (($lti{$itemid}{'roster'}) && (grep(/^Instructor$/, at ltiroles))) {
+ if (($ltihash->{'roster'}) && (grep(/^Instructor$/,@{$ltiroles}))) {
if ($params->{'ext_ims_lis_memberships_id'}) {
- $env{'request.lti.rosterid'} = $params->{'ext_ims_lis_memberships_id'};
+ $env{'request.lti.rosterid'} = $params->{'ext_ims_lis_memberships_id'};
}
if ($params->{'ext_ims_lis_memberships_url'}) {
$env{'request.lti.rosterurl'} = $params->{'ext_ims_lis_memberships_url'};
@@ -591,9 +877,17 @@
$info{'role'} = $role;
}
if ($symb) {
- $info{'symb'} = $symb;
+ $info{'symb'} = $symb;
+ }
+ if (($lcroles->[0] eq 'cc') && ($reqcrs)) {
+ $info{'lti.reqcrs'} = 1;
+ $info{'lti.reqrole'} = 'cc';
+ $info{'lti.sourcecrs'} = $sourcecrs;
+ }
+ if ($selfenrollrole) {
+ $info{'lti.selfenrollrole'} = $selfenrollrole;
}
- if ($lti{$itemid}{'passback'}) {
+ if ($ltihash->{'passback'}) {
if ($params->{'lis_result_sourcedid'}) {
$info{'lti.passbackid'} = $params->{'lis_result_sourcedid'}
}
@@ -601,7 +895,7 @@
$info{'lti.passbackurl'} = $params->{'lis_outcome_service_url'}
}
}
- if (($lti{$itemid}{'roster'}) && (grep(/^Instructor$/, at ltiroles))) {
+ if (($ltihash->{'roster'}) && (grep(/^Instructor$/,@{$ltiroles}))) {
if ($params->{'ext_ims_lis_memberships_id'}) {
$info{'lti.rosterid'} = $params->{'ext_ims_lis_memberships_id'};
}
@@ -612,9 +906,8 @@
unless ($info{'symb'}) {
if ($mapurl) {
$info{'origurl'} = $mapurl;
- if ($mapurl =~ m{/default_\d+\.sequence$}) {
- $info{'origurl'} .= (($mapurl =~/\?/)?'&':'?').'navmap=1';
- }
+ } elsif ($tail =~ m{^\Q/tiny/$cdom/\E\w+$}) {
+ $info{'origurl'} = $tail;
} else {
unless ($tail eq '/adm/roles') {
$info{'origurl'} = '/adm/navmaps';
@@ -629,7 +922,7 @@
$r->internal_redirect('/adm/migrateuser');
$r->set_handlers('PerlHandler'=> undef);
}
- return OK;
+ return;
}
sub invalid_request {
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1367 loncom/lonnet/perl/lonnet.pm:1.1368
--- loncom/lonnet/perl/lonnet.pm:1.1367 Thu Feb 1 04:51:13 2018
+++ loncom/lonnet/perl/lonnet.pm Fri Mar 23 01:02:04 2018
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1367 2018/02/01 04:51:13 raeburn Exp $
+# $Id: lonnet.pm,v 1.1368 2018/03/23 01:02:04 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -7146,6 +7146,7 @@
community => 1,
textbook => 1,
placement => 1,
+ lti => 1,
);
} elsif ($context eq 'requestauthor') {
%tools = (
@@ -7342,25 +7343,29 @@
}
sub check_can_request {
- my ($dom,$can_request,$request_domains) = @_;
+ my ($dom,$can_request,$request_domains,$uname,$udom) = @_;
my $canreq = 0;
+ if (($env{'user.name'} ne '') && ($env{'user.domain'} ne '')) {
+ $uname = $env{'user.name'};
+ $udom = $env{'user.domain'};
+ }
my ($types,$typename) = &Apache::loncommon::course_types();
my @options = ('approval','validate','autolimit');
my $optregex = join('|', at options);
if ((ref($can_request) eq 'HASH') && (ref($types) eq 'ARRAY')) {
foreach my $type (@{$types}) {
- if (&usertools_access($env{'user.name'},
- $env{'user.domain'},
- $type,undef,'requestcourses')) {
+ if (&usertools_access($uname,$udom,$type,undef,
+ 'requestcourses')) {
$canreq ++;
if (ref($request_domains) eq 'HASH') {
- push(@{$request_domains->{$type}},$env{'user.domain'});
+ push(@{$request_domains->{$type}},$udom);
}
- if ($dom eq $env{'user.domain'}) {
+ if ($dom eq $udom) {
$can_request->{$type} = 1;
}
}
- if ($env{'environment.reqcrsotherdom.'.$type} ne '') {
+ if (($env{'user.name'} ne '') && ($env{'user.domain'} ne '') &&
+ ($env{'environment.reqcrsotherdom.'.$type} ne '')) {
my @curr = split(',',$env{'environment.reqcrsotherdom.'.$type});
if (@curr > 0) {
foreach my $item (@curr) {
@@ -7377,7 +7382,7 @@
}
}
}
- unless($dom eq $env{'user.domain'}) {
+ unless ($dom eq $env{'user.domain'}) {
$canreq ++;
if (grep(/^\Q$dom\E:($optregex)(=?\d*)$/, at curr)) {
$can_request->{$type} = 1;
@@ -9298,8 +9303,12 @@
}
}
}
- } elsif (($selfenroll == 1) && ($role eq 'st') && ($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) {
- $refused = '';
+ } elsif (($selfenroll == 1) && ($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) {
+ if ($role eq 'st') {
+ $refused = '';
+ } elsif (($context eq 'ltienroll') && ($env{'request.lti'})) {
+ $refused = '';
+ }
} elsif ($context eq 'requestcourses') {
my @possroles = ('st','ta','ep','in','cc','co');
if ((grep(/^\Q$role\E$/, at possroles)) && ($env{'user.name'} ne '' && $env{'user.domain'} ne '')) {
@@ -9565,10 +9574,14 @@
my $newuser;
if ($uhome eq 'no_host') {
$newuser = 1;
+ unless (($umode && ($upass ne '')) || ($umode eq 'localauth') ||
+ ($umode eq 'lti')) {
+ return 'error: more information needed to create new user';
+ }
}
# ----------------------------------------------------------------- Create User
if (($uhome eq 'no_host') &&
- (($umode && $upass) || ($umode eq 'localauth'))) {
+ (($umode && $upass) || ($umode eq 'localauth') || ($umode eq 'lti'))) {
my $unhome='';
if (defined($desiredhome) && &host_domain($desiredhome) eq $udom) {
$unhome = $desiredhome;
Index: loncom/lond
diff -u loncom/lond:1.542 loncom/lond:1.543
--- loncom/lond:1.542 Thu Feb 1 04:50:41 2018
+++ loncom/lond Fri Mar 23 01:02:22 2018
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.542 2018/02/01 04:50:41 raeburn Exp $
+# $Id: lond,v 1.543 2018/03/23 01:02:22 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -65,7 +65,7 @@
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.542 $'; #' stupid emacs
+my $VERSION='$Revision: 1.543 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid="default";
my $currentdomainid;
@@ -8369,6 +8369,14 @@
$result = "pass_file_failed_error";
}
}
+ } elsif ($umode eq 'lti') {
+ my $pf = IO::File->new(">$passfilename");
+ if($pf) {
+ print $pf "lti:\n";
+ &update_passwd_history($uname,$udom,$umode,$action);
+ } else {
+ $result = "pass_file_failed_error";
+ }
} else {
$result="auth_mode_error";
}
More information about the LON-CAPA-cvs
mailing list