Upstream the Bulk Enroll API endpoint

parent 13e06a37
"""
Serializers for Bulk Enrollment.
"""
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from rest_framework import serializers
class StringListField(serializers.ListField):
def to_internal_value(self, data):
try:
return data[0].split(',')
except IndexError:
return []
class BulkEnrollmentSerializer(serializers.Serializer):
"""Serializes enrollment information for a collection of students/emails.
This is mainly useful for implementing validation when performing bulk enrollment operations.
"""
identifiers = serializers.CharField(required=True)
courses = StringListField(required=True)
action = serializers.ChoiceField(
choices=(
('enroll', 'enroll'),
('unenroll', 'unenroll')
),
required=True
)
auto_enroll = serializers.BooleanField(default=False)
email_students = serializers.BooleanField(default=False)
def validate_courses(self, value):
"""
Check that each course key in list is valid.
"""
course_keys = value
for course in course_keys:
try:
CourseKey.from_string(course)
except InvalidKeyError:
raise serializers.ValidationError("Course key not valid: {}".format(course))
return value
"""
URLs for the Bulk Enrollment API
"""
from django.conf.urls import patterns, url
from bulk_enroll.views import BulkEnrollView
urlpatterns = patterns(
'bulk_enroll.views',
url(r'^bulk_enroll', BulkEnrollView.as_view(), name='bulk_enroll'),
)
"""
API views for Bulk Enrollment
"""
import json
from edx_rest_framework_extensions.authentication import JwtAuthentication
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from bulk_enroll.serializers import BulkEnrollmentSerializer
from enrollment.views import EnrollmentUserThrottle
from instructor.views.api import students_update_enrollment
from openedx.core.lib.api.authentication import OAuth2Authentication
from openedx.core.lib.api.permissions import IsStaff
from util.disable_rate_limit import can_disable_rate_limit
@can_disable_rate_limit
class BulkEnrollView(APIView):
"""
**Use Case**
Enroll multiple users in one or more courses.
**Example Request**
POST /api/bulk_enroll/v1/bulk_enroll/ {
"auto_enroll": true,
"email_students": true,
"action": "enroll",
"courses": "course-v1:edX+Demo+123,course-v1:edX+Demo2+456",
"identifiers": "brandon@example.com,yamilah@example.com"
}
**POST Parameters**
A POST request can include the following parameters.
* auto_enroll: When set to `true`, students will be enrolled as soon
as they register.
* email_students: When set to `true`, students will be sent email
notifications upon enrollment.
* action: Can either be set to "enroll" or "unenroll". This determines the behabior
**Response Values**
If the supplied course data is valid and the enrollments were
successful, an HTTP 200 "OK" response is returned.
The HTTP 200 response body contains a list of response data for each
enrollment. (See the `instructor.views.api.students_update_enrollment`
docstring for the specifics of the response data available for each
enrollment)
"""
authentication_classes = JwtAuthentication, OAuth2Authentication
permission_classes = IsStaff,
throttle_classes = EnrollmentUserThrottle,
def post(self, request):
serializer = BulkEnrollmentSerializer(data=request.data)
if serializer.is_valid():
request.POST = request.data
response_dict = {
'auto_enroll': serializer.data.get('auto_enroll'),
'email_students': serializer.data.get('email_students'),
'action': serializer.data.get('action'),
'courses': {}
}
for course in serializer.data.get('courses'):
response = students_update_enrollment(self.request, course_id=course)
response_dict['courses'][course] = json.loads(response.content)
return Response(data=response_dict, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
......@@ -392,6 +392,9 @@ FEATURES = {
# Whether to check the "Notify users by email" checkbox in the batch enrollment form
# in the instructor dashboard.
'BATCH_ENROLLMENT_NOTIFY_USERS_DEFAULT': True,
# Whether the bulk enrollment view is enabled.
'ENABLE_BULK_ENROLLMENT_VIEW': False,
}
# Settings for the course reviews tool template and identification key, set either to None to disable course reviews
......@@ -2110,6 +2113,9 @@ INSTALLED_APPS = (
# Enrollment API
'enrollment',
# Bulk Enrollment API
'bulk_enroll',
# Student Identity Verification
'lms.djangoapps.verify_student',
......
......@@ -80,6 +80,8 @@ FEATURES['MILESTONES_APP'] = True
FEATURES['ENABLE_ENROLLMENT_TRACK_USER_PARTITION'] = True
FEATURES['ENABLE_BULK_ENROLLMENT_VIEW'] = True
# Need wiki for courseware views to work. TODO (vshnayder): shouldn't need it.
WIKI_ENABLED = True
......
......@@ -806,6 +806,13 @@ if settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD'):
)
if configuration_helpers.get_value('ENABLE_BULK_ENROLLMENT_VIEW',
settings.FEATURES['ENABLE_BULK_ENROLLMENT_VIEW']):
urlpatterns += (
url(r'^api/bulk_enroll/v1/', include('bulk_enroll.urls')),
)
# Shopping cart
urlpatterns += (
url(r'^shoppingcart/', include('shoppingcart.urls')),
......
......@@ -119,6 +119,16 @@ class IsMasterCourseStaffInstructor(permissions.BasePermission):
return False
class IsStaff(permissions.BasePermission):
"""
Permission that checks to see if the request user has is_staff access.
"""
def has_permission(self, request, view):
if request.user.is_staff:
return True
class IsUserInUrlOrStaff(IsUserInUrl):
"""
Permission that checks to see if the request user matches the user in the URL or has is_staff access.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment