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

PADV-1528: Create ViewSet CourseContentItemViewSet #41

Merged
merged 1 commit into from
Aug 19, 2024
Merged

Conversation

kuipumu
Copy link
Contributor

@kuipumu kuipumu commented Aug 12, 2024

Ticket

https://agile-jira.pearson.com/browse/PADV-1528

Description

This PR adds a CourseContentItemViewSet ViewSet to list all the Course content items available for a launch ID. This ViewSet will be used to render a paginated form table in the DeepLinkingFormView template.

Additionally this PR also includes an upgrade to the project requirements.

Type of Change

  • Upgrade project requirements.
  • Move pylti1.3 attributes and functions used on LTI Tool Views to a LTIToolMixin class.
  • Create LTIToolView that inherits from LTIToolMixin and View class.
  • Replace views using LtiToolBaseView with LTIToolView.
  • Add djangorestframework to project requirements.
  • Add base setup for Django REST Framework API.
  • Add CourseContentItemViewSet.
  • Add or modify all tests related to this code.

Testing:

  1. Run the LMS: make dev.up.lms.
  2. Install openedx_lti_tool_plugin on the LMS.
  3. Run ngrok or any other similar service on LMS: ngrok http 18000
  4. Add required settings to LMS.
# Enable LTI Tool Provider Plugin.
OLTITP_ENABLE_LTI_TOOL = True
  1. Create a new LTI 1.3 tool key config: https://lms.ngrok.io/admin/lti1p3_tool_config/ltitoolkey/add/ (You can use IMS RI to create a key pair: https://lti-ri.imsglobal.org/keygen/index)
  2. Create a new LTI 1.3 tool config: https://lms.ngrok.io/admin/lti1p3_tool_config/ltitool/add/
Issuer: https://saltire.lti.app/platform
Client id: saltire.lti.app
Auth login: url: https://saltire.lti.app/platform/auth
Auth token url: https://saltire.lti.app/platform/token/sda42bb0cf2352259a367a404d48d54e8
Key set url: https://saltire.lti.app/platform/jwks/sda42bb0cf2352259a367a404d48d54e8
Deployment ids: ["cLWwj9cbmkSrCNsckEFBmA"]
  1. Go to the saLTIre platform https://saltire.lti.app/platform
  2. Go to "Security Model" on the left sidebar and set these settings:
Message URL: https://lms.ngrok.io/openedx_lti_tool_plugin/1.3/deep_linking/
Initiate login URL: https://lms.ngrok.io/openedx_lti_tool_plugin/1.3/login
Redirection URI(s): https://lms.ngrok.io/openedx_lti_tool_plugin/1.3/deep_linking/
Public keyset URL: https://lms.ngrok.io/openedx_lti_tool_plugin/1.3/pub/jwks
  1. Go to "Message" on the left sidebar and set these settings:
Message type: LtiDeepLinkingRequest
  1. Click on the "Save" button on the top navbar.
  2. Click on the dropdown next to the "Connect" button on the top navbar.
  3. Click on "Open in new window".
  4. You should be redirected to the Deep Linking Form View.
  5. Copy the launch ID from the browser URL (Example: https://lms.ngrok.io/openedx_lti_tool_plugin/1.3/deep_linking//).
  6. Go to the URL https://lms.ngrok.io/openedx_lti_tool_plugin/1.3/deep_linking/api/v1//content_items/courses
  7. You should be presented with a list of paginated content items for all the courses available for the LtiTool.

max_page_size = 100


class CourseContentItemViewSet(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kuipumu Aren't authentication_classes and permission_classes necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anfbermudezme I forgot to add the JwtAuthentication class, but there are no permission classes necessary since this API endpoint is used by unauthenticated users.

from openedx_lti_tool_plugin.utils import get_identity_claims


class ContentItemPagination(PageNumberPagination):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kuipumu How about having a separate module for pagination? (pagination.py)

CourseContext QuerySet.

"""
iss, aud, _sub, _pii = get_identity_claims(self.launch_data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kuipumu Please explain what is iss, aud, _sub, _pii.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anfbermudezme The get_identity_claims function has a docstring with references to the OpenID Connect Core 1.0 ID token claims and standard claims, I will add a comment in this line to explain why we are obtaining the iss and aud claim

"""
iss, aud, _sub, _pii = get_identity_claims(self.launch_data)

return CourseContext.objects\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kuipumu

Suggested change
return CourseContext.objects\
return CourseContext.objects.all_for_lti_tool(iss, aud).filter_by_site_orgs()

from openedx_lti_tool_plugin.views import requires_plugin_enabled


@method_decorator(requires_plugin_enabled, name='dispatch')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@method_decorator(requires_plugin_enabled, name='dispatch')
@method_decorator(requires_plugin_enabled, name='dispatch')

@kuipumu The name of this decorator is too general. Which plugin is required to be enabled?



@method_decorator(requires_openedx_lti_tool_plugin_enabled, name='dispatch')
class DeepLinkingViewSet(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be more of a base view?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexjmpb It's a base view, I followed a similar structure found in rest_framework/viewsets.py for other ViewSets such has ModelViewSet, are you suggesting we use a different name for this View or are you suggesting a different structure for the API Views?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it was more of a naming question, but it's not that relevant.

@@ -274,10 +275,10 @@ def __str__(self) -> str:
return f'<CourseAccessConfiguration, ID: {self.id}>'


class CourseContextManager(models.Manager):
"""CourseContext Model Manager."""
class CourseContextQuerySet(models.QuerySet):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you decided to change this to a queryset?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexjmpb I changed it to a queryset so I was able to chain the all_for_lti_tool and filter_by_site_orgs querysets, with a Manager I would have to create a Queryset and duplicate the methods of such Queryset in the manager, the as_manager method does that for you automatically: https://docs.djangoproject.com/en/5.0/topics/db/managers/#creating-a-manager-with-queryset-methods

refactor: LTI Tool Views
feat: Upgrade requirements
@kuipumu kuipumu merged commit aa1c27c into main Aug 19, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants