Skip to content

Commit

Permalink
Merge pull request #680 from edx/sameen/ENT-2042-EnrollmentApiClient
Browse files Browse the repository at this point in the history
Changed name of EnrollmentApiClientJwt back to its original name
  • Loading branch information
sameenfatima78 authored Jan 16, 2020
2 parents beaf5af + b48f303 commit 7e0c709
Show file tree
Hide file tree
Showing 19 changed files with 144 additions and 341 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ Change Log

.. There should always be an "Unreleased" section for changes pending release.
[2.0.50] - 2020-01-16
---------------------

* Replaced EnrollmentApiClientJwt name back to original client's name.

[2.0.49] - 2020-01-15
---------------------

Expand Down
2 changes: 1 addition & 1 deletion enterprise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

from __future__ import absolute_import, unicode_literals

__version__ = "2.0.49"
__version__ = "2.0.50"

default_app_config = "enterprise.apps.EnterpriseConfig" # pylint: disable=invalid-name
4 changes: 2 additions & 2 deletions enterprise/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
EnterpriseCustomerTransmitCoursesView,
TemplatePreviewView,
)
from enterprise.api_client.lms import CourseApiClient, EnrollmentApiClientJwt
from enterprise.api_client.lms import CourseApiClient, EnrollmentApiClient
from enterprise.models import (
EnrollmentNotificationEmailTemplate,
EnterpriseCatalogQuery,
Expand Down Expand Up @@ -369,7 +369,7 @@ def _get_all_enrollments(self, enterprise_customer_user):
enterprise_customer_user: The instance of EnterpriseCustomerUser
being rendered with this admin form.
"""
enrollment_client = EnrollmentApiClientJwt(enterprise_customer_user.user)
enrollment_client = EnrollmentApiClient(enterprise_customer_user.user)
enrollments = enrollment_client.get_enrolled_courses(enterprise_customer_user.username)
return [enrollment['course_details']['course_id'] for enrollment in enrollments]

Expand Down
4 changes: 2 additions & 2 deletions enterprise/admin/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
)
from enterprise.admin.widgets import SubmitInput
from enterprise.api_client.discovery import CourseCatalogApiClient
from enterprise.api_client.lms import EnrollmentApiClientJwt
from enterprise.api_client.lms import EnrollmentApiClient
from enterprise.models import (
EnterpriseCustomer,
EnterpriseCustomerCatalog,
Expand Down Expand Up @@ -211,7 +211,7 @@ def clean_course(self):
if not course_id:
return None
try:
client = EnrollmentApiClientJwt(self._user)
client = EnrollmentApiClient(self._user)
return client.get_course_details(course_id)
except (HttpClientError, HttpServerError):
raise ValidationError(ValidationMessages.INVALID_COURSE_ID.format(course_id=course_id))
Expand Down
6 changes: 3 additions & 3 deletions enterprise/admin/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
validate_email_to_link,
)
from enterprise.api_client.ecommerce import EcommerceApiClient
from enterprise.api_client.lms import EnrollmentApiClientJwt
from enterprise.api_client.lms import EnrollmentApiClient
from enterprise.constants import PAGE_SIZE
from enterprise.models import (
EnrollmentNotificationEmailTemplate,
Expand Down Expand Up @@ -443,7 +443,7 @@ def enroll_user(cls, enterprise_customer, user, course_mode, *course_ids):
enterprise_customer=enterprise_customer,
user_id=user.id
)
enrollment_client = EnrollmentApiClientJwt(user)
enrollment_client = EnrollmentApiClient(user)
succeeded = True
for course_id in course_ids:
try:
Expand Down Expand Up @@ -489,7 +489,7 @@ def is_user_enrolled(cls, user, course_id, course_mode):
Boolean: Whether or not enrollment exists
"""
enrollment_client = EnrollmentApiClientJwt(user)
enrollment_client = EnrollmentApiClient(user)
try:
enrollments = enrollment_client.get_course_enrollment(user.username, course_id)
if enrollments and course_mode == enrollments.get('mode'):
Expand Down
190 changes: 1 addition & 189 deletions enterprise/api_client/lms.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,201 +133,13 @@ def redirect_if_blocked(course_run_ids, user=None, ip_address=None, url=None):
return redirect_url


class EnrollmentApiClient(LmsApiClient):
class EnrollmentApiClient(JwtLmsApiClient):
"""
Object builds an API client to make calls to the Enrollment API.
"""

API_BASE_URL = settings.ENTERPRISE_ENROLLMENT_API_URL

def get_course_details(self, course_id):
"""
Query the Enrollment API for the course details of the given course_id.
Args:
course_id (str): The string value of the course's unique identifier
Returns:
dict: A dictionary containing details about the course, in an enrollment context (allowed modes, etc.)
"""
try:
return self.client.course(course_id).get()
except (SlumberBaseException, ConnectionError, Timeout) as exc:
LOGGER.exception(
'Failed to retrieve course enrollment details for course [%s] due to: [%s]',
course_id, str(exc)
)
return {}

def _sort_course_modes(self, modes):
"""
Sort the course mode dictionaries by slug according to the COURSE_MODE_SORT_ORDER constant.
Arguments:
modes (list): A list of course mode dictionaries.
Returns:
list: A list with the course modes dictionaries sorted by slug.
"""
def slug_weight(mode):
"""
Assign a weight to the course mode dictionary based on the position of its slug in the sorting list.
"""
sorting_slugs = COURSE_MODE_SORT_ORDER
sorting_slugs_size = len(sorting_slugs)
if mode['slug'] in sorting_slugs:
return sorting_slugs_size - sorting_slugs.index(mode['slug'])
return 0
# Sort slug weights in descending order
return sorted(modes, key=slug_weight, reverse=True)

def get_course_modes(self, course_id):
"""
Query the Enrollment API for the specific course modes that are available for the given course_id.
Arguments:
course_id (str): The string value of the course's unique identifier
Returns:
list: A list of course mode dictionaries.
"""
details = self.get_course_details(course_id)
modes = details.get('course_modes', [])
return self._sort_course_modes([mode for mode in modes if mode['slug'] not in EXCLUDED_COURSE_MODES])

def has_course_mode(self, course_run_id, mode):
"""
Query the Enrollment API to see whether a course run has a given course mode available.
Arguments:
course_run_id (str): The string value of the course run's unique identifier
Returns:
bool: Whether the course run has the given mode avaialble for enrollment.
"""
course_modes = self.get_course_modes(course_run_id)
return any(course_mode for course_mode in course_modes if course_mode['slug'] == mode)

def enroll_user_in_course(self, username, course_id, mode, cohort=None):
"""
Call the enrollment API to enroll the user in the course specified by course_id.
Args:
username (str): The username by which the user goes on the OpenEdX platform
course_id (str): The string value of the course's unique identifier
mode (str): The enrollment mode which should be used for the enrollment
cohort (str): Add the user to this named cohort
Returns:
dict: A dictionary containing details of the enrollment, including course details, mode, username, etc.
"""
return self.client.enrollment.post(
{
'user': username,
'course_details': {'course_id': course_id},
'mode': mode,
'cohort': cohort,
}
)

def unenroll_user_from_course(self, username, course_id):
"""
Call the enrollment API to unenroll the user in the course specified by course_id.
Args:
username (str): The username by which the user goes on the OpenEdx platform
course_id (str): The string value of the course's unique identifier
Returns:
bool: Whether the unenrollment succeeded
"""
enrollment = self.get_course_enrollment(username, course_id)
if enrollment and enrollment['is_active']:
response = self.client.enrollment.post({
'user': username,
'course_details': {'course_id': course_id},
'is_active': False,
'mode': enrollment['mode']
})
return not response['is_active']

return False

def get_course_enrollment(self, username, course_id):
"""
Query the enrollment API to get information about a single course enrollment.
Args:
username (str): The username by which the user goes on the OpenEdX platform
course_id (str): The string value of the course's unique identifier
Returns:
dict: A dictionary containing details of the enrollment, including course details, mode, username, etc.
"""
endpoint = getattr(
self.client.enrollment,
'{username},{course_id}'.format(username=username, course_id=course_id)
)
try:
result = endpoint.get()
except HttpNotFoundError:
# This enrollment data endpoint returns a 404 if either the username or course_id specified isn't valid
LOGGER.error(
'Course enrollment details not found for invalid username or course; username=[%s], course=[%s]',
username,
course_id
)
return None
# This enrollment data endpoint returns an empty string if the username and course_id is valid, but there's
# no matching enrollment found
if not result:
LOGGER.info('Failed to find course enrollment details for user [%s] and course [%s]', username, course_id)
return None

return result

def is_enrolled(self, username, course_run_id):
"""
Query the enrollment API and determine if a learner is enrolled in a course run.
Args:
username (str): The username by which the user goes on the OpenEdX platform
course_run_id (str): The string value of the course's unique identifier
Returns:
bool: Indicating whether the user is enrolled in the course run. Returns False under any errors.
"""
enrollment = self.get_course_enrollment(username, course_run_id)
return enrollment is not None and enrollment.get('is_active', False)

def get_enrolled_courses(self, username):
"""
Query the enrollment API to get a list of the courses a user is enrolled in.
Args:
username (str): The username by which the user goes on the OpenEdX platform
Returns:
list: A list of course objects, along with relevant user-specific enrollment details.
"""
return self.client.enrollment.get(user=username)


class EnrollmentApiClientJwt(JwtLmsApiClient):
"""
Object builds an API client to make calls to the Enrollment API.
The Edx_Api_Key has been deprecated which is why we are shifting to this new client that is based on
JwtLmsApiClient. In the future, if anyone wants to use EnrollmentApiClient client, make sure to use this one and
not the original one.
"""

API_BASE_URL = settings.ENTERPRISE_ENROLLMENT_API_URL

@JwtLmsApiClient.refresh_token
def get_course_details(self, course_id):
"""
Expand Down
8 changes: 4 additions & 4 deletions enterprise/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
from enterprise import utils
from enterprise.api_client.discovery import CourseCatalogApiClient, get_course_catalog_api_service_client
from enterprise.api_client.ecommerce import EcommerceApiClient
from enterprise.api_client.lms import EnrollmentApiClientJwt, ThirdPartyAuthApiClientJwt, parse_lms_api_datetime
from enterprise.api_client.lms import EnrollmentApiClient, ThirdPartyAuthApiClientJwt, parse_lms_api_datetime
from enterprise.constants import ALL_ACCESS_CONTEXT, ENTERPRISE_OPERATOR_ROLE, json_serialized_course_modes
from enterprise.utils import (
CourseEnrollmentDowngradeError,
Expand Down Expand Up @@ -734,7 +734,7 @@ def enroll(self, course_run_id, mode, cohort=None, source_slug=None):
"""
Enroll a user into a course track, and register an enterprise course enrollment.
"""
enrollment_api_client = EnrollmentApiClientJwt(self.user)
enrollment_api_client = EnrollmentApiClient(self.user)
# Check to see if the user's already enrolled and we have an enterprise course enrollment to track it.
course_enrollment = enrollment_api_client.get_course_enrollment(self.username, course_run_id) or {}
enrolled_in_course = course_enrollment and course_enrollment.get('is_active', False)
Expand Down Expand Up @@ -797,7 +797,7 @@ def unenroll(self, course_run_id):
"""
Unenroll a user from a course track.
"""
enrollment_api_client = EnrollmentApiClientJwt(self.user)
enrollment_api_client = EnrollmentApiClient(self.user)
if enrollment_api_client.unenroll_user_from_course(self.username, course_run_id):
EnterpriseCourseEnrollment.objects.filter(enterprise_customer_user=self, course_id=course_run_id).delete()
return True
Expand Down Expand Up @@ -1199,7 +1199,7 @@ def is_audit_enrollment(self):
:return: Whether the course enrollment mode is of an audit type.
"""
course_enrollment_api = EnrollmentApiClientJwt(self.enterprise_customer_user.user)
course_enrollment_api = EnrollmentApiClient(self.enterprise_customer_user.user)
course_enrollment = course_enrollment_api.get_course_enrollment(
self.enterprise_customer_user.username,
self.course_id
Expand Down
14 changes: 7 additions & 7 deletions enterprise/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from enterprise.api.v1.serializers import EnterpriseCustomerUserWriteSerializer
from enterprise.api_client.discovery import get_course_catalog_api_service_client
from enterprise.api_client.ecommerce import EcommerceApiClient
from enterprise.api_client.lms import CourseApiClient, EmbargoApiClient, EnrollmentApiClientJwt
from enterprise.api_client.lms import CourseApiClient, EmbargoApiClient, EnrollmentApiClient
from enterprise.decorators import enterprise_login_required, force_fresh_session
from enterprise.forms import ENTERPRISE_SELECT_SUBTITLE, EnterpriseSelectionForm
from enterprise.models import (
Expand Down Expand Up @@ -941,7 +941,7 @@ def get(self, request, enterprise_uuid, course_id):
if not enrollment_course_mode:
return redirect(LMS_DASHBOARD_URL)

enrollment_api_client = EnrollmentApiClientJwt(request.user)
enrollment_api_client = EnrollmentApiClient(request.user)
course_modes = enrollment_api_client.get_course_modes(course_id)

# Verify that the request user belongs to the enterprise against the
Expand Down Expand Up @@ -1051,7 +1051,7 @@ def get_available_course_modes(self, request, course_run_id, enterprise_catalog)
course modes returned using the EnterpriseCustomerCatalog's
field "enabled_course_modes".
"""
modes = EnrollmentApiClientJwt(request.user).get_course_modes(course_run_id)
modes = EnrollmentApiClient(request.user).get_course_modes(course_run_id)
if not modes:
LOGGER.warning('[Enterprise Enrollment] Unable to get course modes. '
'CourseRun: {course_run_id}'.format(course_run_id=course_run_id))
Expand Down Expand Up @@ -1394,7 +1394,7 @@ def post(self, request, enterprise_uuid, course_id):
)
track_enrollment('course-landing-page-enrollment', request.user.id, course_id, request.get_full_path())

client = EnrollmentApiClientJwt(request.user)
client = EnrollmentApiClient(request.user)
client.enroll_user_in_course(
request.user.username,
course_id,
Expand Down Expand Up @@ -1497,7 +1497,7 @@ def get(self, request, enterprise_uuid, course_id):
enterprise_customer=enterprise_customer
)

enrollment_client = EnrollmentApiClientJwt(request.user)
enrollment_client = EnrollmentApiClient(request.user)
enrolled_course = enrollment_client.get_course_enrollment(request.user.username, course_id)
try:
enterprise_course_enrollment = EnterpriseCourseEnrollment.objects.get(
Expand Down Expand Up @@ -1975,7 +1975,7 @@ def get_course_run_id(user, enterprise_customer, course_key):
except ImproperlyConfigured:
raise Http404

users_all_enrolled_courses = EnrollmentApiClientJwt(user).get_enrolled_courses(user.username)
users_all_enrolled_courses = EnrollmentApiClient(user).get_enrolled_courses(user.username)
users_active_course_runs = get_active_course_runs(
course,
users_all_enrolled_courses
Expand Down Expand Up @@ -2004,7 +2004,7 @@ def eligible_for_direct_audit_enrollment(self, request, enterprise_customer, res
return request.GET.get('audit') and \
request.path == self.COURSE_ENROLLMENT_VIEW_URL.format(enterprise_customer.uuid, course_identifier) and \
enterprise_customer.catalog_contains_course(resource_id) and \
EnrollmentApiClientJwt(request.user).has_course_mode(resource_id, 'audit')
EnrollmentApiClient(request.user).has_course_mode(resource_id, 'audit')

def redirect(self, request, *args, **kwargs):
"""
Expand Down
Loading

0 comments on commit 7e0c709

Please sign in to comment.