feat: replace learning_assistant_launch_url with learning_assistant_enabled in courseware API

This commit replaces the learning_assistant_launch_url field of the CoursewareInformation view of the courseware API with a learning_assistant_enabled field. learning_assistant_enabled is a boolean that represents whether the Xpert Learning Assistant is enabled for the requesting user, based on the associated CourseWaffleFlag. This change is necessary because we are no longer leveraging the Learning Assistant LTI tool.
This commit is contained in:
michaelroytman
2023-08-07 15:59:15 -04:00
parent 4fd2241896
commit 7598a81b57
4 changed files with 12 additions and 160 deletions

View File

@@ -114,7 +114,7 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract-
linkedin_add_to_profile_url = serializers.URLField()
is_integrity_signature_enabled = serializers.BooleanField()
user_needs_integrity_signature = serializers.BooleanField()
learning_assistant_launch_url = serializers.CharField()
learning_assistant_enabled = serializers.BooleanField()
def __init__(self, *args, **kwargs):
"""

View File

@@ -11,13 +11,10 @@ import ddt
from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing
from django.conf import settings
from django.contrib.auth import get_user_model
from django.test import override_settings
from django.test.client import RequestFactory
from edx_django_utils.cache import TieredCache
from edx_toggles.toggles.testutils import override_waffle_flag
from lti_consumer.data import Lti1p3LaunchData
from lti_consumer.models import LtiConfiguration
from xmodule.data import CertificatesDisplayBehaviors
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@@ -434,109 +431,16 @@ class CourseApiTestViews(BaseCoursewareTests, MasqueradeMixin):
assert courseware_data['can_access_proctored_exams'] == result
@override_waffle_flag(COURSEWARE_LEARNING_ASSISTANT, active=False)
def test_learning_assistant_launch_url_disabled_waffle_flag(self):
def test_learning_assistant_enabled_disabled_waffle_flag(self):
response = self.client.get(self.url)
launch_url = response.json()['learning_assistant_launch_url']
assert launch_url is None
learning_assistant_enabled = response.json()['learning_assistant_enabled']
self.assertFalse(learning_assistant_enabled)
@override_waffle_flag(COURSEWARE_LEARNING_ASSISTANT, active=True)
@override_settings(LEARNING_ASSISTANT_CONFIG_ID=None)
def test_learning_assistant_launch_no_config(self):
def test_learning_assistant_enabled_enabled_waffle_flag(self):
response = self.client.get(self.url)
launch_url = response.json()['learning_assistant_launch_url']
assert launch_url is None
@override_waffle_flag(COURSEWARE_LEARNING_ASSISTANT, active=True)
def test_learning_assistant_launch_1p1(self):
test_config = LtiConfiguration.objects.create(
config_id=1,
version='lti_1p1'
)
with override_settings(LEARNING_ASSISTANT_CONFIG_ID=test_config.id):
response = self.client.get(self.url)
launch_url = response.json()['learning_assistant_launch_url']
assert launch_url is None
@override_waffle_flag(COURSEWARE_LEARNING_ASSISTANT, active=True)
def test_learning_assistant_launch_not_staff_unverified(self):
test_config = LtiConfiguration.objects.create(
config_id=1,
version='lti_1p3'
)
with override_settings(LEARNING_ASSISTANT_CONFIG_ID=test_config.id):
self.user.is_staff = False
self.user.save()
CourseEnrollment.enroll(self.user, self.course.id, 'audit')
response = self.client.get(self.url)
launch_url = response.json()['learning_assistant_launch_url']
assert launch_url is None
@ddt.data(
'verified',
'professional',
'masters',
'executive-education',
'paid-executive-education',
'paid-bootcamp'
)
@mock.patch('openedx.core.djangoapps.courseware_api.utils.get_lti_1p3_launch_start_url')
@override_waffle_flag(COURSEWARE_LEARNING_ASSISTANT, active=True)
def test_learning_assistant_launch_url(self, enrollment_mode, mock_lti_launch):
test_config = LtiConfiguration.objects.create(
config_id=1,
version='lti_1p3'
)
with override_settings(LEARNING_ASSISTANT_CONFIG_ID=test_config.id):
self.user.is_staff = False
self.user.save()
CourseEnrollment.enroll(self.user, self.course.id, enrollment_mode)
expected_url = 'https://testlaunch.org'
mock_lti_launch.return_value = expected_url
response = self.client.get(self.url)
launch_url = response.json()['learning_assistant_launch_url']
assert launch_url == expected_url
expected_launch_data = Lti1p3LaunchData(
user_id=self.user.id,
user_role='student',
email=self.user.email,
config_id=1,
resource_link_id='-'.join(['1', str(self.course.id)]),
context_id=str(self.course.id),
context_type=['course_offering'],
context_title=self.course.display_name
)
mock_lti_launch.assert_called_with(expected_launch_data)
@mock.patch('openedx.core.djangoapps.courseware_api.utils.get_lti_1p3_launch_start_url')
@override_waffle_flag(COURSEWARE_LEARNING_ASSISTANT, active=True)
def test_learning_assistant_launch_url_instructor(self, mock_lti_launch):
self.client.login(username='instructor', password='foo')
test_config = LtiConfiguration.objects.create(
config_id=1,
version='lti_1p3'
)
with override_settings(LEARNING_ASSISTANT_CONFIG_ID=test_config.id):
expected_url = 'https://testlaunch.org'
mock_lti_launch.return_value = expected_url
response = self.client.get(self.url)
launch_url = response.json()['learning_assistant_launch_url']
assert launch_url == expected_url
expected_launch_data = Lti1p3LaunchData(
user_id=self.instructor.id,
user_role='instructor',
email=self.instructor.email,
config_id=1,
resource_link_id='-'.join(['1', str(self.course.id)]),
context_id=str(self.course.id),
context_type=['course_offering'],
context_title=self.course.display_name
)
mock_lti_launch.assert_called_with(expected_launch_data)
learning_assistant_enabled = response.json()['learning_assistant_enabled']
self.assertTrue(learning_assistant_enabled)
@ddt.ddt

View File

@@ -3,15 +3,9 @@ Courseware API Mixins.
"""
from babel.numbers import get_currency_symbol
from django.conf import settings
from lti_consumer.api import get_lti_1p3_launch_start_url
from lti_consumer.data import Lti1p3LaunchData
from lti_consumer.models import LtiConfiguration
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.models import CourseEnrollmentCelebration, UserCelebration
from lms.djangoapps.courseware.access import get_user_role
from lms.djangoapps.courseware.utils import can_show_verified_upgrade, verified_upgrade_deadline_link
from openedx.features.course_duration_limits.access import get_user_course_expiration_date
from openedx.features.discounts.applicability import can_show_streak_discount_coupon
@@ -72,41 +66,3 @@ def serialize_upgrade_info(user, course_overview, enrollment):
'sku': mode.sku,
'upgrade_url': verified_upgrade_deadline_link(user, course_overview),
}
def get_learning_assistant_launch_url(user, course_key, enrollment_object, overview):
"""
Return the launch URL for an LTI based learning assistant
"""
config_id = getattr(settings, 'LEARNING_ASSISTANT_CONFIG_ID', None)
if not config_id:
return None
try:
lti_config = LtiConfiguration.objects.get(config_id=config_id)
except LtiConfiguration.DoesNotExist:
return None
if lti_config.version != 'lti_1p3':
return None
user_role = get_user_role(user, course_key)
if (
(enrollment_object and enrollment_object.mode not in CourseMode.VERIFIED_MODES)
and (user_role != 'staff' or user_role != 'instructor')
):
return None
launch_data = Lti1p3LaunchData(
user_id=user.id,
user_role=user_role,
email=user.email,
config_id=config_id,
resource_link_id='-'.join([str(config_id), str(course_key)]),
context_id=str(course_key),
context_type=['course_offering'],
context_title=overview.display_name
)
lti_url = get_lti_1p3_launch_start_url(launch_data)
return lti_url

View File

@@ -47,7 +47,7 @@ from lms.djangoapps.gating.api import get_entrance_exam_score, get_entrance_exam
from lms.djangoapps.grades.api import CourseGradeFactory
from lms.djangoapps.verify_student.services import IDVerificationService
from openedx.core.djangoapps.agreements.api import get_integrity_signature
from openedx.core.djangoapps.courseware_api.utils import get_celebrations_dict, get_learning_assistant_launch_url
from openedx.core.djangoapps.courseware_api.utils import get_celebrations_dict
from openedx.core.djangoapps.programs.utils import ProgramProgressMeter
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin
@@ -360,19 +360,11 @@ class CoursewareMeta:
return enrollment_active and CourseMode.is_eligible_for_certificate(enrollment_mode)
@property
def learning_assistant_launch_url(self):
def learning_assistant_enabled(self):
"""
Returns a URL for the learning assistant LTI launch if applicable, otherwise None
Returns a boolean representing whether the requesting user should have access to the Xpert Learning Assistant.
"""
if learning_assistant_is_active(self.course_key):
lti_url = get_learning_assistant_launch_url(
self.effective_user,
self.course_key,
self.enrollment_object,
self.overview,
)
return lti_url
return None
return learning_assistant_is_active(self.course_key)
class CoursewareInformation(RetrieveAPIView):
@@ -463,7 +455,7 @@ class CoursewareInformation(RetrieveAPIView):
verified mode. Will update to reverify URL if necessary.
* linkedin_add_to_profile_url: URL to add the effective user's certificate to a LinkedIn Profile.
* user_needs_integrity_signature: Whether the user needs to sign the integrity agreement for the course
* learning_assistant_launch_url: URL for the LTI launch of a learning assistant
* learning_assistant_enabled: Whether the Xpert Learning Assistant is enabled for the requesting user
**Parameters:**