allow course-related variable expansions for NRPS

why:
  Course-related variable expansions aren't exposed

flag=none
refs INTEROP-6600

--------------------------------------------------
Test plan
(requires the LTI 1.3 Test Tool)
--------------------------------------------------
* Activate the feature flag "LTI Deep Linking for Module Index
  Menu"

* Install a LTI Tool with the placement "module_index_menu_modal"
  using the message_type "LtiDeepLinkingRequest"

* Go to Course > Module page

* Click on the 3 dots button-menu in the top of the page and
  launch the tool

* the "Deep Linking" page should open

* add the custom variables in the "Custom Params (JSON)" field.
  Example:
```
{
   "canvas_course_endAt":"$Canvas.course.endAt",
   "canvas_course_gradePassbackSetting":"$Canvas.course.gradePassbackSetting",
   "canvas_course_hideDistributionGraphs":"$Canvas.course.hideDistributionGraphs",
   "canvas_course_id":"$Canvas.course.id",
   "canvas_course_name":"$Canvas.course.name",
   "canvas_course_previousContextIds":"$Canvas.course.previousContextIds",
   "canvas_course_previousContextIds_recursive":"$Canvas.course.previousContextIds.recursive",
   "canvas_course_previousCourseIds":"$Canvas.course.previousCourseIds",
   "canvas_course_sectionIds":"$Canvas.course.sectionIds",
   "canvas_course_sectionRestricted":"$Canvas.course.sectionRestricted",
   "canvas_course_sectionSisSourceIds":"$Canvas.course.sectionSisSourceIds",
   "canvas_course_sisSourceId":"$Canvas.course.sisSourceId",
   "canvas_course_startAt":"$Canvas.course.startAt",
   "canvas_course_workflowState":"$Canvas.course.workflowState"
}
```

* click on "Send Deep Link to Platform"

* open the assignment created to launch the tool

* in the "Decoded JWT" field, check in the JSON for the key
  "https://purl.imsglobal.org/spec/lti/claim/custom". There
  should be the requested custom variables



Change-Id: Icbe518b67dc62da7b056af31feb5be85f13b6104
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/294961
Reviewed-by: Tucker Mcknight <tmcknight@instructure.com>
QA-Review: Tucker Mcknight <tmcknight@instructure.com>
Product-Review: Alexis Nast <alexis.nast@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
This commit is contained in:
Alexandre Trindade 2022-06-28 12:36:37 -03:00
parent 8103deac08
commit 549bce4115
2 changed files with 127 additions and 19 deletions

View File

@ -53,6 +53,11 @@ module Lti::IMS
end
def variable_expander(enrollment)
# the variables substitution in the whitelist have the following guards:
# - @current_user
# - @context.is_a?(Course)
# - @tool
Lti::VariableExpander.new(
page[:context].root_account,
Lti::IMS::Providers::MembershipsProvider.unwrap(page[:context]),
@ -62,29 +67,42 @@ module Lti::IMS
tool: page[:tool],
enrollment: enrollment,
variable_whitelist: %w[
Person.name.full
Person.name.display
Person.name.family
Person.name.given
User.image
User.id
Canvas.user.id
vnd.instructure.User.uuid
com.instructure.User.sectionNames
Caliper.url
Canvas.course.endAt
Canvas.course.gradePassbackSetting
Canvas.course.hideDistributionGraphs
Canvas.course.id
Canvas.course.name
Canvas.course.previousContextIds
Canvas.course.previousContextIds.recursive
Canvas.course.previousCourseIds
Canvas.course.sectionIds
Canvas.course.sectionRestricted
Canvas.course.sectionSisSourceIds
Canvas.course.sisSourceId
Canvas.course.startAt
Canvas.course.workflowState
Canvas.group.contextIds
Canvas.user.globalId
Canvas.user.sisSourceId
Person.sourcedId
Message.locale
vnd.Canvas.Person.email.sis
Person.email.primary
Person.address.timezone
User.username
Canvas.user.id
Canvas.user.loginId
Canvas.user.sisIntegrationId
Canvas.course.sectionIds
Canvas.group.contextIds
Canvas.user.sisSourceId
Canvas.xapi.url
Caliper.url
Message.locale
Person.address.timezone
Person.email.primary
Person.name.display
Person.name.family
Person.name.full
Person.name.given
Person.sourcedId
User.id
User.image
User.username
com.instructure.User.sectionNames
vnd.Canvas.Person.email.sis
vnd.instructure.User.uuid
]
}
)

View File

@ -76,6 +76,44 @@ describe Lti::IMS::NamesAndRolesSerializer do
})
end
shared_context "course and tool for variable substitution" do
let(:course) do
course = super()
course.name = "Brand new course"
course.start_at = 3.days.ago
course.conclude_at = 1.day.ago
course.grade_passback_setting = "nightly_sync"
course.save!
course
end
let(:tool) do
tool = super()
tool.settings[:custom_fields] = {
canvas_course_endAt: "$Canvas.course.endAt",
canvas_course_gradePassbackSetting: "$Canvas.course.gradePassbackSetting",
canvas_course_hideDistributionGraphs: "$Canvas.course.hideDistributionGraphs",
canvas_course_id: "$Canvas.course.id",
canvas_course_name: "$Canvas.course.name",
canvas_course_previousContextIds: "$Canvas.course.previousContextIds",
canvas_course_previousContextIds_recursive: "$Canvas.course.previousContextIds.recursive",
canvas_course_previousCourseIds: "$Canvas.course.previousCourseIds",
canvas_course_sectionIds: "$Canvas.course.sectionIds",
canvas_course_sectionRestricted: "$Canvas.course.sectionRestricted",
canvas_course_sectionSisSourceIds: "$Canvas.course.sectionSisSourceIds",
canvas_course_sisSourceId: "$Canvas.course.sisSourceId",
canvas_course_startAt: "$Canvas.course.startAt",
canvas_course_workflowState: "$Canvas.course.workflowState"
}
tool.save!
tool
end
let(:page) do
super().merge(opts: { rlid: "rlid-value" })
end
end
shared_examples "enrollment serialization" do
it "properly formats NRPS json" do
json = serialize
@ -224,6 +262,33 @@ describe Lti::IMS::NamesAndRolesSerializer do
end
it_behaves_like "serializes message array if rlid param present"
context "variables expansion" do
include_context "course and tool for variable substitution"
it "expand course-related variables from the tool settings" do
json = serialize
received_custom_claim = json[:members][0][:message].first["https://purl.imsglobal.org/spec/lti/claim/custom"]
expect(received_custom_claim["canvas_course_endat"]).to eq course.end_at.utc.iso8601
expect(received_custom_claim["canvas_course_gradepassbacksetting"]).to eq course.grade_passback_setting
expect(received_custom_claim["canvas_course_hidedistributiongraphs"]).to eq course.hide_distribution_graphs?
expect(received_custom_claim["canvas_course_id"]).to eq course.id
expect(received_custom_claim["canvas_course_name"]).to eq course.name
lti_helper = Lti::SubstitutionsHelper.new(course, course.root_account, user, tool)
expect(received_custom_claim["canvas_course_previouscontextids"]).to eq lti_helper.previous_lti_context_ids
expect(received_custom_claim["canvas_course_previouscontextids_recursive"]).to eq lti_helper.recursively_fetch_previous_lti_context_ids
expect(received_custom_claim["canvas_course_previouscourseids"]).to eq lti_helper.previous_course_ids
expect(received_custom_claim["canvas_course_sectionids"]).to eq lti_helper.section_ids
expect(received_custom_claim["canvas_course_sectionrestricted"]).to eq lti_helper.section_restricted
expect(received_custom_claim["canvas_course_sectionsissourceids"]).to eq lti_helper.section_sis_ids
expect(received_custom_claim["canvas_course_sissourceid"]).to eq course.sis_source_id
expect(received_custom_claim["canvas_course_startat"]).to eq course.start_at.utc.iso8601
expect(received_custom_claim["canvas_course_workflowstate"]).to eq course.workflow_state
end
end
end
context "with a group" do
@ -283,6 +348,31 @@ describe Lti::IMS::NamesAndRolesSerializer do
end
it_behaves_like "serializes message array if rlid param present"
context "variables expansion" do
include_context "course and tool for variable substitution"
it "does not expand course-related variables from the tool settings" do
# the variable expander needs the Course as a @context
json = serialize
received_custom_claim = json[:members][0][:message].first["https://purl.imsglobal.org/spec/lti/claim/custom"]
expect(received_custom_claim["canvas_course_endat"]).to eq "$Canvas.course.endAt"
expect(received_custom_claim["canvas_course_gradepassbacksetting"]).to eq "$Canvas.course.gradePassbackSetting"
expect(received_custom_claim["canvas_course_hidedistributiongraphs"]).to eq "$Canvas.course.hideDistributionGraphs"
expect(received_custom_claim["canvas_course_id"]).to eq "$Canvas.course.id"
expect(received_custom_claim["canvas_course_name"]).to eq "$Canvas.course.name"
expect(received_custom_claim["canvas_course_previouscontextids"]).to eq "$Canvas.course.previousContextIds"
expect(received_custom_claim["canvas_course_previouscontextids_recursive"]).to eq "$Canvas.course.previousContextIds.recursive"
expect(received_custom_claim["canvas_course_previouscourseids"]).to eq "$Canvas.course.previousCourseIds"
expect(received_custom_claim["canvas_course_sectionids"]).to eq "$Canvas.course.sectionIds"
expect(received_custom_claim["canvas_course_sectionrestricted"]).to eq "$Canvas.course.sectionRestricted"
expect(received_custom_claim["canvas_course_sectionsissourceids"]).to eq "$Canvas.course.sectionSisSourceIds"
expect(received_custom_claim["canvas_course_sissourceid"]).to eq "$Canvas.course.sisSourceId"
expect(received_custom_claim["canvas_course_startat"]).to eq "$Canvas.course.startAt"
expect(received_custom_claim["canvas_course_workflowstate"]).to eq "$Canvas.course.workflowState"
end
end
end
end
end