Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more configurable LTI variables to config page. #2447

Merged
merged 5 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion conf/authen_LTI.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,43 @@ $LTIMassUpdateInterval = 86400; #in seconds
# the tab will not be shown. Note that the default values for the variables that will be shown
# in the LTI tab are the values that are set above. Further note that only the commented out
# variables listed below may be added to the LTI config tab. In addition, only the variables that
# pertain to the active LTI version will be shown in the tab.
# pertain to the active LTI version will be shown in the tab. Warning: Allowing users to modify
# the BasicConsumerSecret for LTI 1.1 or the IDs, URLs, etc for LTI 1.3 can expose the values
# of the variables and allow users to lock themselves out of logging in via an LMS.
@LTIConfigVariables = (
#'LTI{v1p1}{LMS_name}',
#'LTI{v1p3}{LMS_name}',
#'LTI{v1p1}{LMS_url}',
#'LTI{v1p3}{LMS_url}',
#'external_auth',
#'LTIGradeMode',
#'LTIGradeOnSubmit',
#'LTIMassUpdateInterval',
#'LMSManageUserData',
#'LTI{v1p1}{BasicConsumerSecret}',
#'LTI{v1p3}{PlatformID}',
#'LTI{v1p3}{ClientID}',
#'LTI{v1p3}{DeploymentID}',
#'LTI{v1p3}{PublicKeysetURL}',
#'LTI{v1p3}{AccessTokenURL}',
#'LTI{v1p3}{AccessTokenAUD}',
#'LTI{v1p3}{AuthReqURL}',
#'debug_lti_parameters',
#'lms_context_id'
);

# By default only admin users can modify the LTI secrets and lms_context_id. The following
# permissions need to be modified to allow other users the permission to modify the values.
#$permissionLevels{'change_config_LTI{v1p1}{BasicConsumerSecret}'} = "admin",
#$permissionLevels{'change_config_LTI{v1p3}{PlatformID}'} = "admin",
#$permissionLevels{'change_config_LTI{v1p3}{ClientID}'} = "admin",
#$permissionLevels{'change_config_LTI{v1p3}{DeploymentID}'} = "admin",
#$permissionLevels{'change_config_LTI{v1p3}{PublicKeysetURL}'} = "admin",
#$permissionLevels{'change_config_LTI{v1p3}{AccessTokenURL}'} = "admin",
#$permissionLevels{'change_config_LTI{v1p3}{AccessTokenAUD}'} = "admin",
#$permissionLevels{'change_config_LTI{v1p3}{AuthReqURL}'} = "admin",
#$permissionLevels{'change_config_lms_context_id'} = "admin",

# Note that the lms_context_id is actually a database setting. It must be set for a course in
# order for the instructor to utilize LTI content selection. This can also be set in the admin
# course.
Expand Down
10 changes: 9 additions & 1 deletion conf/defaults.config
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,15 @@ $authen{admin_module} = ['WeBWorK::Authen::Basic_TheLastOption'];
# sufficient to change a configuration setting.

#change_config_courseTitle => "admin",
change_config_lms_context_id => "admin",
change_config_lms_context_id => "admin",
'change_config_LTI{v1p1}{BasicConsumerSecret}' => "admin",
'change_config_LTI{v1p3}{PlatformID}' => "admin",
'change_config_LTI{v1p3}{ClientID}' => "admin",
'change_config_LTI{v1p3}{DeploymentID}' => "admin",
'change_config_LTI{v1p3}{PublicKeysetURL}' => "admin",
'change_config_LTI{v1p3}{AccessTokenURL}' => "admin",
'change_config_LTI{v1p3}{AccessTokenAUD}' => "admin",
'change_config_LTI{v1p3}{AuthReqURL}' => "admin",

# Do not confuse the permission to change a configuration permission with
# the actual permission as in the following example. If this us uncommented,
Expand Down
9 changes: 5 additions & 4 deletions lib/WeBWorK/ConfigObject.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package WeBWorK::ConfigObject;
use Mojo::Base -signatures;

# Base object class for all config objects
use constant SECRET_STRING => '*****';

sub new ($class, $data, $c) {
return bless {
Expand All @@ -13,7 +14,7 @@ sub new ($class, $data, $c) {

# Only input is a value to display, and should produce an html string.
sub display_value ($self, $val) {
return $val;
return $self->{secret} ? SECRET_STRING : $val;
}

# This should return the value to compare to the new value. This is *not* what is displayed.
Expand Down Expand Up @@ -47,16 +48,16 @@ sub convert_newval_source ($self, $use_current) {
# will be the value of the perl variable, and newval will be whatever an entry widget produces.
sub save_string ($self, $oldval, $use_current = 0) {
my $newval = $self->convert_newval_source($use_current);
return '' if $self->comparison_value($oldval) eq $newval;
return '' if $self->comparison_value($oldval) eq $newval || ($self->{secret} && $newval eq SECRET_STRING);

$newval =~ s/['"`]//g;
return "\$$self->{var} = '$newval';\n";
}

# A widget to interact with the user
sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
return $self->{c}->text_field(
$self->{name} => $default,
$self->{name} => $is_secret ? SECRET_STRING : $default,
id => $self->{name},
size => $self->{width} || 15,
class => 'form-control form-control-sm'
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ConfigObject/boolean.pm
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ sub save_string ($self, $oldval, $use_current = 0) {
return "\$$self->{var} = $newval;\n";
}

sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
return $self->{c}->select_field(
$self->{name} => [
[ $self->{c}->maketext('True') => 1, $default == 1 ? (selected => undef) : () ],
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ConfigObject/checkboxlist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ sub comparison_value ($self, $val) {
return join(',', @{ $val // [] });
}

sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
my $c = $self->{c};
return $c->c(
map {
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ConfigObject/list.pm
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ sub save_string ($self, $oldval, $use_current = 0) {
return "\$$self->{var} = [" . join(',', map {"'$_'"} map { $_ =~ s/['"`]//gr } split(',', $newval)) . "];\n";
}

sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
my $str = join(', ', @{ $default // [] });
return $self->{c}->text_area(
$self->{name} => $str =~ /\S/ ? $str : '',
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ConfigObject/lms_context_id.pm
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ sub save_string ($self, $oldval, $use_current = 0) {

# This ensures that the input for this setting always shows what is in the database. If the form is submitted, and the
# requested context id is rejected above, then that rejected value should not be shown when the page reloads.
sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
$self->{c}->param($self->{name}, $default);
return $self->SUPER::entry_widget($default);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ConfigObject/permission.pm
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sub save_string ($self, $oldval, $use_current = 0) {
return "\$$self->{var} = '$newval';\n";
}

sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
my $c = $self->{c};

# The value of a permission can be undefined (for nobody), a standard permission number, or some other number
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ConfigObject/permission_checkboxlist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ sub comparison_value ($self, $val) {
return join(',', @{ $val // [] });
}

sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
my $c = $self->{c};
$default = role_and_above($self->{c}->ce->{userRoles}, $default) unless ref($default) eq 'ARRAY';
return $c->c(
Expand Down
2 changes: 1 addition & 1 deletion lib/WeBWorK/ConfigObject/popuplist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ sub save_string ($self, $oldval, $use_current = 0) {
return ("\$$self->{var} = '$newval';\n");
}

sub entry_widget ($self, $default) {
sub entry_widget ($self, $default, $is_secret = 0) {
my $c = $self->{c};
return $c->select_field(
$self->{name} => [
Expand Down
87 changes: 87 additions & 0 deletions lib/WeBWorK/ConfigValues.pm
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,25 @@ sub getConfigValues ($ce) {
labels => { '' => 'None', 'course' => 'Course', 'homework' => 'Homework' },
type => 'popuplist'
},
LTIGradeOnSubmit => {
var => 'LTIGradeOnSubmit',
doc => x('Update LMS Grade Each Submit'),
doc2 => x(
'Sets if webwork sends grades back to the LMS every time a user submits an answer. '
. 'This keeps students grades up to date, but can cause additional server load.'
),
type => 'boolean'
},
LTIMassUpdateInterval => {
var => 'LTIMassUpdateInterval',
doc => x('Time in seconds to periodically update LMS grades (-1 to disable)'),
doc2 => x(
'Sets the time in seconds to periodically update the LMS grades. WeBWorK will update all grades on '
. 'the LMS if it has been longer than this time since the completion of the last update. This is '
. 'only an approximate time. 86400 seconds is one day. -1 disables periodic updates.'
),
type => 'number'
},
LMSManageUserData => {
var => 'LMSManageUserData',
doc => x('Allow the LMS to update user account data'),
Expand All @@ -902,6 +921,65 @@ sub getConfigValues ($ce) {
),
type => 'boolean'
},
'LTI{v1p1}{BasicConsumerSecret}' => {
var => 'LTI{v1p1}{BasicConsumerSecret}',
doc => x('LMS shared secret for LTI 1.1 authentication'),
doc2 => x(
'This secret word is used to validate logins from an LMS using LTI 1.1. '
. 'This secret word must match the word configured in the LMS.'
),
type => 'text',
secret => 1
},
'LTI{v1p3}{PlatfromID}' => {
var => 'LTI{v1p3}{PlatformID}',
doc => x('LMS platform ID for LTI 1.3'),
doc2 => x('LMS platform ID used to validate logins from an LMS using LTI 1.3.'),
type => 'text',
secret => 1
},
'LTI{v1p3}{ClientID}' => {
var => 'LTI{v1p3}{ClientID}',
doc => x('LMS client ID for LTI 1.3'),
doc2 => x('LMS client ID used to validate logins from an LMS using LTI 1.3.'),
type => 'text',
secret => 1
},
'LTI{v1p3}{DeploymentID}' => {
var => 'LTI{v1p3}{DeploymentID}',
doc => x('LMS deployment ID for LTI 1.3'),
doc2 => x('LMS deployment ID used to validate logins from an LMS using LTI 1.3.'),
type => 'text',
secret => 1
},
'LTI{v1p3}{PublicKeysetURL}' => {
var => 'LTI{v1p3}{PublicKeysetURL}',
doc => x('LMS public keyset URL for LTI 1.3'),
doc2 => x('LMS public keyset URL used to validate logins from an LMS using LTI 1.3.'),
type => 'text',
secret => 1
},
'LTI{v1p3}{AccessTokenURL}' => {
var => 'LTI{v1p3}{AccessTokenURL}',
doc => x('LMS access token URL for LTI 1.3'),
doc2 => x('LMS access token URL used to validate logins from an LMS using LTI 1.3.'),
type => 'text',
secret => 1
},
'LTI{v1p3}{AccessTokenAUD}' => {
var => 'LTI{v1p3}{AccessTokenAUD}',
doc => x('LMS access token AUD for LTI 1.3'),
doc2 => x('LMS access token AUD used to validate logins from an LMS using LTI 1.3.'),
type => 'text',
secret => 1
},
'LTI{v1p3}{AuthReqURL}' => {
var => 'LTI{v1p3}{AuthReqURL}',
doc => x('LMS authorization request URL for LTI 1.3'),
doc2 => x('LMS authorization request URL used to validate logins from an LMS using LTI 1.3.'),
type => 'text',
secret => 1
},
debug_lti_parameters => {
var => 'debug_lti_parameters',
doc => x('Show LTI parameters (for debugging)'),
Expand Down Expand Up @@ -988,6 +1066,15 @@ sub getConfigValues ($ce) {
{ %{ delete $LTIConfigValues->{'LTI{v1p1}{LMS_name}'} }, var => 'LTI{v1p3}{LMS_name}' };
$LTIConfigValues->{'LTI{v1p3}{LMS_url}'} =
{ %{ delete $LTIConfigValues->{'LTI{v1p1}{LMS_url}'} }, var => 'LTI{v1p3}{LMS_url}' };
delete $LTIConfigValues->{'LTI{v1p1}{BasicConsumerSecret}'};
} else {
for my $key (
'PlatformID', 'ClientID', 'DeploymentID', 'PublicKeysetURL',
'AccessTokenURL', 'AccessTokenAUD', 'AuthReqURL'
)
{
delete $LTIConfigValues->{"LTI{v1p3}{$key}"};
}
}

push(
Expand Down
6 changes: 5 additions & 1 deletion templates/ContentGenerator/Instructor/Config.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@
% defined $ce->{permissionLevels}{"change_config_$conobject->{var}"}
% && !$authz->hasPermissions(param('user'), "change_config_$conobject->{var}")
% );
% # Hide sensitive variables from being displayed.
% my $default_value = $conobject->get_value($default_ce);
% my $current_value = $conobject->get_value($ce3);
% my $is_secret = $conobject->{secret} && $default_value eq $current_value ? 1 : 0;
<tr>
<td><%= $conobject->what_string %></td>
<td class="text-center">
<%= $conobject->display_value($conobject->get_value($default_ce)) %>
</td>
<td><%= $conobject->entry_widget($conobject->get_value($ce3)) =%></td>
<td><%= $conobject->entry_widget($conobject->get_value($ce3), $is_secret) =%></td>
</tr>
% }
</table>
Expand Down