Skip to content

Commit

Permalink
Use DB configured canvas assignments in launches
Browse files Browse the repository at this point in the history
  • Loading branch information
marcospri committed Sep 23, 2021
1 parent d6b01f8 commit a7a096a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 23 deletions.
8 changes: 8 additions & 0 deletions lms/resources/_js_config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ def add_document_url(self, document_url):
_query={"document_url": document_url},
),
}

elif document_url.startswith("canvas://"):
self.add_canvas_file_id(
self._request.params["custom_canvas_course_id"],
self._request.params["resource_link_id"],
self._request.params["file_id"],
)

else:
self._config["viaUrl"] = via_url(self._request, document_url)
self._add_canvas_speedgrader_settings(document_url=document_url)
Expand Down
27 changes: 13 additions & 14 deletions lms/views/basic_lti_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,36 +94,35 @@ def store_lti_data(self):
@view_config(canvas_file=True)
def canvas_file_basic_lti_launch(self):
"""
Respond to a Canvas file assignment launch.
Respond to a Canvas file assignment launch which is not db_configured.
Canvas file assignment launch requests have a ``file_id`` request
parameter, which is the Canvas instance's ID for the file. To display
the assignment we have to use this ``file_id`` to get a download URL
for the file from the Canvas API. We then pass that download URL to
Via. We have to re-do this file-ID-for-download-URL exchange on every
single launch because Canvas's download URLs are temporary.
"""
Note that this only apply to assignments configured but not yet launched
after canvas assignments are also DB configured see: js_config._create_assignment_api
"""
course_id = self.request.params["custom_canvas_course_id"]
file_id = self.request.params["file_id"]
resource_link_id = self.request.params["resource_link_id"]

# Normally this would be done during `configure_assignment()` but
# Canvas skips that step. We are doing this to ensure that there is a
# module item configuration. As a result of this we can rely on this
# being around in future code.
# This URL is mostly for show. We just want to ensure that a module
# configuration exists. If we're going to do that we might as well
# make sure this URL is meaningful.
document_url = f"canvas://file/course/{course_id}/file_id/{file_id}"

# Newly configured canvas assignments make it to the database
# but for exiting ones that never got launched we keep this call to persist them.
self.assignment_service.set_document_url(
self.request.params["tool_consumer_instance_guid"],
# This URL is mostly for show. We just want to ensure that a module
# configuration exists. If we're going to do that we might as well
# make sure this URL is meaningful.
document_url=f"canvas://file/course/{course_id}/file_id/{file_id}",
document_url=document_url,
resource_link_id=resource_link_id,
)

self.context.js_config.add_canvas_file_id(course_id, resource_link_id, file_id)

return self.basic_lti_launch(grading_supported=False)
return self.basic_lti_launch(document_url=document_url, grading_supported=False)

@view_config(vitalsource_book=True)
def vitalsource_lti_launch(self):
Expand Down
23 changes: 20 additions & 3 deletions lms/views/predicates/_lti_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ def db_configured_assignment_launch_view(context, request):
def __call__(self, context, request):
assignment_svc = request.find_service(name="assignment")
resource_link_id = request.params.get("resource_link_id")
ext_lti_assignment_id = request.params.get("ext_lti_assignment_id")
tool_consumer_instance_guid = request.params.get("tool_consumer_instance_guid")

return (
assignment_svc.exists(tool_consumer_instance_guid, resource_link_id)
assignment_svc.exists(
tool_consumer_instance_guid, resource_link_id, ext_lti_assignment_id
)
== self.value
)

Expand Down Expand Up @@ -159,6 +162,8 @@ class CanvasFile(Base):
"""
Allow invoking an LTI launch view only for Canvas file assignments.
Newer Canvas file assignment are already present in the DB so they behave like DB Configured ones.
Pass ``canvas_file=True`` to a view config to allow invoking the view only
for Canvas file assignments, or ``canvas_file=False`` to allow it only for
other types of assignment. For example::
Expand All @@ -168,10 +173,16 @@ def canvas_file_assignment_launch_view(context, request):
...
"""

def __init__(self, value, config):
super().__init__(value, config)
self.db_configured = DBConfigured(True, config)

name = "canvas_file"

def __call__(self, context, request):
return ("canvas_file" in request.params) == self.value
return ("canvas_file" in request.params) == self.value and self.db_configured(
context, request
) != self.value


class VitalSourceBook(Base):
Expand Down Expand Up @@ -203,8 +214,14 @@ def url_configured_assignment_launch_view(context, request):

name = "url_configured"

def __init__(self, value, config):
super().__init__(value, config)
self.db_configured = DBConfigured(True, config)

def __call__(self, context, request):
return ("url" in request.params) == self.value
return ("url" in request.params) == self.value and self.db_configured(
context, request
) != self.value


class Configured(Base):
Expand Down
6 changes: 0 additions & 6 deletions tests/unit/lms/views/basic_lti_launch_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,6 @@ class TestCanvasFileBasicLTILaunch:
def test_it(self, context, pyramid_request, assignment_service):
canvas_file_basic_lti_launch_caller(context, pyramid_request)

context.js_config.add_canvas_file_id.assert_called_once_with(
pyramid_request.params["custom_canvas_course_id"],
pyramid_request.params["resource_link_id"],
pyramid_request.params["file_id"],
)

course_id = pyramid_request.params["custom_canvas_course_id"]
file_id = pyramid_request.params["file_id"]

Expand Down

0 comments on commit a7a096a

Please sign in to comment.