Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
53c74e5
feat(models): split LTI 1.3 configuration into separate Passport model
navinkarkera Mar 18, 2026
64a4af8
feat(lti): add signal handlers for LTI configuration deletion
navinkarkera Mar 19, 2026
73ed221
fix(lti): correct spelling and improve logging in signal handlers
navinkarkera Mar 19, 2026
76c138e
fix: lint issues
navinkarkera Mar 19, 2026
e7ee13f
feat: install openedx-events
navinkarkera Mar 19, 2026
42b0058
fix: model label
navinkarkera Mar 19, 2026
d87f83b
fix: handle no location
navinkarkera Mar 19, 2026
d39335d
test: fix tests
navinkarkera Mar 20, 2026
ff4adb2
fix: lint issues
navinkarkera Mar 20, 2026
02dba13
fixup! fix: lint issues
navinkarkera Mar 20, 2026
e6f764b
test: add signal tests
navinkarkera Mar 22, 2026
33a3af6
fix: coverage
navinkarkera Mar 22, 2026
02d60a1
refactor(models): rename create_lti_1p3_passport to get_or_create_lti…
navinkarkera Mar 24, 2026
475d2b5
fix: copy-paste bug when both public key and keyset url is specified
navinkarkera Mar 26, 2026
4ca5319
fix: lint issues
navinkarkera Mar 26, 2026
bda0876
test: improve coverage
navinkarkera Mar 26, 2026
4151f3a
refactor(views): remove unnecessary db call
navinkarkera Mar 26, 2026
6ad08c9
feat: add name and context key to passport and fix race condition
navinkarkera Mar 31, 2026
e18ab8c
fix: create name only if block is available
navinkarkera Mar 31, 2026
ae83e71
fix: test
navinkarkera Mar 31, 2026
df218ac
refactor: migration
navinkarkera Apr 3, 2026
993d7e0
chore: upgrade
navinkarkera Apr 3, 2026
73223f0
refactor: avoid duplicate signal triggers
navinkarkera Apr 3, 2026
a3540e9
refactor: api
navinkarkera Apr 3, 2026
a044512
refactor: rename
navinkarkera Apr 3, 2026
4e274e5
fix: tests
navinkarkera Apr 3, 2026
37634b2
chore: fix lint issues
navinkarkera Apr 3, 2026
e079a36
test: add some more
navinkarkera Apr 3, 2026
fedb4fb
fix: tests
navinkarkera Apr 3, 2026
8b68c1a
fix: coverage issue
navinkarkera Apr 3, 2026
c4c890b
chore: upgrade
navinkarkera Apr 7, 2026
e8199d6
fix: handle duplicate block explicitly
navinkarkera Apr 7, 2026
5ee39f8
fix: upgrade conflicts
navinkarkera Apr 13, 2026
f0672c5
refactor: robust duplicate signal handler
navinkarkera Apr 13, 2026
748c3ed
fix: migration for missing location field in configurations
navinkarkera Apr 14, 2026
b16c9bb
fix: lint issues
navinkarkera Apr 14, 2026
d8a7b7f
refactor: remove logic that update block fields in migration
navinkarkera Apr 16, 2026
a416676
refactor: add passport id to xml
navinkarkera Apr 16, 2026
6cd6122
fix(migrations): restore config fields from passport on reverse
navinkarkera Apr 18, 2026
965fe7f
refactor: apply suggestions and update docs
navinkarkera Apr 18, 2026
b07e30a
feat: bump version and update changelog
navinkarkera Apr 18, 2026
058609a
docs: Update lti_consumer/lti_xblock.py
feanil Apr 19, 2026
25e555f
docs: Update lti_consumer/migrations/0021_create_lti_1p3_passport.py
feanil Apr 19, 2026
90051fa
fix: remove unrelated file
navinkarkera Apr 20, 2026
5fae419
fix: update requirements
navinkarkera Apr 20, 2026
8e5b926
refactor: remove save_xblock helper
navinkarkera Apr 20, 2026
fac60e2
test: fix tests
navinkarkera Apr 20, 2026
63d762b
fix: ags result endpoint to work with or without ending slash
navinkarkera Apr 9, 2026
e92c06a
fix: allow blank comment in scores api endpoint
navinkarkera Apr 9, 2026
44297e6
fix: use correct deep linking launch uri as target_link_uri
navinkarkera Apr 12, 2026
b294d2d
fix: lint issues
navinkarkera Apr 12, 2026
b035647
fix: use correct key-secret pair for lti 1.1
navinkarkera Apr 17, 2026
53003e3
feat: new role maps
navinkarkera Apr 15, 2026
7453c14
test: improve tests
navinkarkera Apr 15, 2026
8b82583
fix(lti-1p3): include forum roles in launch user role
navinkarkera Apr 15, 2026
9485734
fix: lint issues
navinkarkera Apr 15, 2026
e6fe86d
test: improve
navinkarkera Apr 15, 2026
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
3 changes: 2 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
[run]
data_file = .coverage
source = lti_consumer
omit = */urls.py
omit =
*/urls.py
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Please See the `releases tab <https://github.com/openedx/xblock-lti-consumer/rel
Unreleased
~~~~~~~~~~

11.0.1 - 2026-04-20
--------------------
* Split LTI 1.3 Configuration into Passport Model
* Fix duplicate, copy-paste for LTI xblocks
* Add signal handlers for events like delete, duplicate etc.

10.0.1 - 2026-03-17
--------------------
* Revert the quoting of location/usage_keys done in version 9.14.4 & 9.14.5.
Expand Down
166 changes: 166 additions & 0 deletions docs/decisions/0008-lti-1p3-role-mapping-update.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
LTI 1.3 roles mapping update
----------------------------

Status
======

Provisional

Context
=======

Open edX LTI 1.3 launch code historically mapped course roles to institution and system role URIs.
This caused interoperability problems with tools that expect context role URIs in LTI launch and NRPS
membership responses.

LTI 1.3 roles claim allows role URIs from published LIS vocabularies, including:

* system roles
* institution roles
* context roles

In practice, LTI launches in Open edX happen in course context, so context roles are most relevant.
Open edX also has more explicit role values than ``staff``, ``instructor``, ``student``, and ``guest``.
These include course roles such as ``limited_staff``, ``finance_admin``, ``sales_admin``,
``beta_testers``, ``library_user``, ``ccx_coach``, and ``data_researcher``.
Open edX also defines discussion roles such as ``Administrator``, ``Moderator``,
``Group Moderator``, ``Community TA``, and ``Student``.

This ADR records updated mapping used for:

* LTI 1.3 launch roles claim
* LTI NRPS membership container member roles

This ADR supersedes Roles section from ``0002-lti-1p3-variables.rst``.

Decisions
=========

Launch roles claim
~~~~~~~~~~~~~~~~~~

For LTI launches, Open edX includes context role URIs plus neutral system and institution role URIs:

* ``http://purl.imsglobal.org/vocab/lis/v2/system/person#None``
* ``http://purl.imsglobal.org/vocab/lis/v2/institution/person#None``

Context role mapping is shown below.

.. list-table::
:widths: auto
:header-rows: 1

* - Open edX role
- LTI 1.3 roles included
- Reasoning
* - instructor
- ``system/person#None``
``institution/person#None``
``membership#Administrator``
``membership#Instructor``
- Course admin role in Open edX maps to highest course-context privilege.
* - staff
- ``system/person#None``
``institution/person#None``
``membership#Instructor``
- Course staff should have instructor-level context access, but not course admin role.
* - limited_staff
- ``system/person#None``
``institution/person#None``
``membership#Instructor``
- Limited staff derives from staff and should expose same course-context role to tools.
* - student
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- Standard learner mapping.
* - guest
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- Guest launch paths use learner-compatible mapping for interoperability.
* - finance_admin
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- No stronger LTI-specific course-context privilege required.
* - sales_admin
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- No stronger LTI-specific course-context privilege required.
* - beta_testers
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- No stronger LTI-specific course-context privilege required.
* - library_user
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- No stronger LTI-specific course-context privilege required.
* - ccx_coach
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- No stronger LTI-specific course-context privilege required.
* - data_researcher
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- No stronger LTI-specific course-context privilege required.
* - org_course_creator_group
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- Org-scoped role does not imply elevated privilege in specific course launch context.
* - course_creator_group
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- Platform-wide role does not imply elevated privilege in specific course launch context.
* - support
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- Support role should not expose elevated course-context privilege to tools by default.
* - Administrator, Moderator, Student
- ``system/person#None``
``institution/person#None``
``membership#Learner``
- Discussion roles do not map cleanly to elevated LTI course-context privilege, so default to learner.
* - Group Moderator, Community TA
- ``system/person#None``
``institution/person#None``
``membership#Learner``
``membership#TeachingAssistant``
- These discussion roles align with teaching-assistant style participation in course context.

NRPS membership roles
~~~~~~~~~~~~~~~~~~~~~

For NRPS membership responses, Open edX includes context roles only.

.. list-table::
:widths: auto
:header-rows: 1

* - Open edX role
- NRPS roles included
* - instructor
- ``membership#Administrator`` ``membership#Instructor``
* - staff
- ``membership#Instructor``
* - limited_staff
- ``membership#Instructor``
* - Group Moderator, Community TA
- ``membership#Learner`` ``membership#TeachingAssistant``
* - all other explicitly mapped roles
- ``membership#Learner``

Consequences
============

* Tool compatibility improves because context role URIs are now present in launch and NRPS flows.
* Open edX role handling becomes explicit for current known course and org role values.
* Older documentation in ``0002-lti-1p3-variables.rst`` remains historical and should not be treated as current source of truth for roles mapping.
2 changes: 1 addition & 1 deletion lti_consumer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .apps import LTIConsumerApp
from .lti_xblock import LtiConsumerXBlock

__version__ = '10.0.1'
__version__ = '11.0.0'
34 changes: 34 additions & 0 deletions lti_consumer/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,33 @@
from lti_consumer.forms import CourseAllowPIISharingInLTIAdminForm
from lti_consumer.models import (
CourseAllowPIISharingInLTIFlag,
Lti1p3Passport,
LtiAgsLineItem,
LtiAgsScore,
LtiConfiguration,
LtiDlContentItem,
)


class LtiConfigurationInline(admin.TabularInline):
"""
Inline for the LtiConfiguration models in Lti1p3Passport.
"""
model = LtiConfiguration
extra = 0
can_delete = False
fields = ('location',)

def has_change_permission(self, request, obj=None): # pragma: nocover
return False

def has_delete_permission(self, request, obj=None): # pragma: nocover
return False

def has_add_permission(self, request, obj=None): # pragma: nocover
return False


@admin.register(LtiConfiguration)
class LtiConfigurationAdmin(admin.ModelAdmin):
"""
Expand All @@ -24,6 +44,20 @@ class LtiConfigurationAdmin(admin.ModelAdmin):
readonly_fields = ('location', 'config_id')


@admin.register(Lti1p3Passport)
class Lti1p3PassportAdmin(admin.ModelAdmin):
"""
Admin view for Lti1p3Passport models.
"""
list_display = (
'name',
'context_key',
'passport_id',
'lti_1p3_client_id',
)
inlines = [LtiConfigurationInline]


@admin.register(CourseAllowPIISharingInLTIFlag)
class CourseAllowPIISharingInLTIFlagAdmin(KeyedConfigurationModelAdmin):
"""
Expand Down
Loading
Loading