Merge PR #27188 bd03/api/post
* Commits: feat: Implement POST endpoint for discussions API feat: Implement update helper for discussions API feat: Implement to_internal_value helper for discussion API feat: Add lti_configuration to discussions API payload refactor: Base discussions serializer off of ModelSerializer refactor: Remove unused helper from discussions API fix: Use the correct name for serializer to_internal_value
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Handle view-logic for the djangoapp
|
||||
"""
|
||||
from lti_consumer.models import LtiConfiguration
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from opaque_keys import InvalidKeyError
|
||||
from rest_framework import serializers
|
||||
@@ -26,6 +27,20 @@ PROVIDER_FEATURE_MAP = {
|
||||
}
|
||||
|
||||
|
||||
class LtiSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
Serialize LtiConfiguration responses
|
||||
"""
|
||||
class Meta:
|
||||
model = LtiConfiguration
|
||||
fields = [
|
||||
'lti_1p1_client_key',
|
||||
'lti_1p1_client_secret',
|
||||
'lti_1p1_launch_url',
|
||||
'version',
|
||||
]
|
||||
|
||||
|
||||
@view_auth_classes()
|
||||
class DiscussionsConfigurationView(APIView):
|
||||
"""
|
||||
@@ -33,36 +48,45 @@ class DiscussionsConfigurationView(APIView):
|
||||
"""
|
||||
permission_classes = (IsStaff,)
|
||||
|
||||
class Serializer(serializers.BaseSerializer):
|
||||
class Serializer(serializers.ModelSerializer):
|
||||
"""
|
||||
Serialize configuration responses
|
||||
"""
|
||||
class Meta:
|
||||
model = DiscussionsConfiguration
|
||||
fields = [
|
||||
'context_key',
|
||||
'enabled',
|
||||
'provider_type',
|
||||
]
|
||||
|
||||
def create(self, validated_data):
|
||||
"""
|
||||
Create and save a new instance
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def to_internal_data(self, data):
|
||||
def to_internal_value(self, data):
|
||||
"""
|
||||
Transform the *incoming* primitive data into a native value.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
payload = {
|
||||
'context_key': data.get('course_key', ''),
|
||||
'enabled': data.get('enabled', False),
|
||||
'lti_configuration': data.get('lti_configuration', {}),
|
||||
'plugin_configuration': data.get('plugin_configuration', {}),
|
||||
'provider_type': data.get('provider_type', ''),
|
||||
}
|
||||
return payload
|
||||
|
||||
def to_representation(self, instance) -> dict:
|
||||
"""
|
||||
Serialize data into a dictionary, to be used as a response
|
||||
"""
|
||||
payload = {
|
||||
'context_key': str(instance.context_key),
|
||||
'enabled': instance.enabled,
|
||||
payload = super().to_representation(instance)
|
||||
lti_configuration = LtiSerializer(instance.lti_configuration)
|
||||
payload.update({
|
||||
'features': {
|
||||
'discussion-page',
|
||||
'embedded-course-sections',
|
||||
'lti',
|
||||
'wcag-2.1',
|
||||
},
|
||||
'lti_configuration': lti_configuration.data,
|
||||
'plugin_configuration': instance.plugin_configuration,
|
||||
'providers': {
|
||||
'active': instance.provider_type or None,
|
||||
@@ -73,14 +97,36 @@ class DiscussionsConfigurationView(APIView):
|
||||
for provider in instance.available_providers
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
return payload
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""
|
||||
Update and save an existing instance
|
||||
"""
|
||||
raise NotImplementedError
|
||||
keys = [
|
||||
'enabled',
|
||||
'plugin_configuration',
|
||||
'provider_type',
|
||||
]
|
||||
for key in keys:
|
||||
value = validated_data.get(key)
|
||||
if value is not None:
|
||||
setattr(instance, key, value)
|
||||
lti_configuration_data = validated_data.get('lti_configuration')
|
||||
if lti_configuration_data:
|
||||
lti_key = lti_configuration_data.get('lti_1p1_client_key')
|
||||
lti_secret = lti_configuration_data.get('lti_1p1_client_secret')
|
||||
lti_url = lti_configuration_data.get('lti_1p1_launch_url')
|
||||
lti_configuration = instance.lti_configuration or LtiConfiguration()
|
||||
lti_configuration.config_store = LtiConfiguration.CONFIG_ON_DB
|
||||
lti_configuration.lti_1p1_client_key = lti_key
|
||||
lti_configuration.lti_1p1_client_secret = lti_secret
|
||||
lti_configuration.lti_1p1_launch_url = lti_url
|
||||
lti_configuration.save()
|
||||
instance.lti_configuration = lti_configuration
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
# pylint: disable=redefined-builtin
|
||||
def get(self, request, course_key_string, **_kwargs) -> Response:
|
||||
@@ -92,6 +138,19 @@ class DiscussionsConfigurationView(APIView):
|
||||
serializer = self.Serializer(configuration)
|
||||
return Response(serializer.data)
|
||||
|
||||
def post(self, request, course_key_string, **_kwargs) -> Response:
|
||||
"""
|
||||
Handle HTTP/POST requests
|
||||
|
||||
TODO: Should we cleanup orphaned LTI config when swapping to cs_comments_service?
|
||||
"""
|
||||
course_key = self._validate_course_key(course_key_string)
|
||||
configuration = DiscussionsConfiguration.get(course_key)
|
||||
serializer = self.Serializer(configuration, data=request.data, partial=True)
|
||||
if serializer.is_valid(raise_exception=True):
|
||||
serializer.save()
|
||||
return Response(serializer.data)
|
||||
|
||||
def _validate_course_key(self, course_key_string: str) -> CourseKey:
|
||||
"""
|
||||
Validate and parse a course_key string, if supported
|
||||
|
||||
Reference in New Issue
Block a user