* feat: add studio_access attribute to metadata * fix: styling errors * fix: remove redunant return
150 lines
6.5 KiB
Python
150 lines
6.5 KiB
Python
"""
|
|
General view for the Course Home that contains metadata every page needs.
|
|
"""
|
|
|
|
from django.db import transaction
|
|
from django.utils.decorators import method_decorator
|
|
from opaque_keys.edx.keys import CourseKey
|
|
from rest_framework.generics import RetrieveAPIView
|
|
from rest_framework.response import Response
|
|
|
|
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
|
|
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
|
|
from lms.djangoapps.certificates.api import certificates_viewable_for_course
|
|
from lms.djangoapps.course_home_api.toggles import new_discussion_sidebar_view_is_enabled
|
|
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
|
|
from openedx.core.djangoapps.courseware_api.utils import get_celebrations_dict
|
|
|
|
from common.djangoapps.course_modes.models import CourseMode
|
|
from common.djangoapps.student.models import CourseEnrollment
|
|
from lms.djangoapps.course_api.api import course_detail
|
|
from lms.djangoapps.course_goals.models import UserActivity
|
|
from lms.djangoapps.course_home_api.course_metadata.serializers import CourseHomeMetadataSerializer
|
|
from lms.djangoapps.courseware.access import has_access, has_cms_access
|
|
from lms.djangoapps.courseware.context_processor import user_timezone_locale_prefs
|
|
from lms.djangoapps.courseware.courses import check_course_access
|
|
from lms.djangoapps.courseware.masquerade import setup_masquerade
|
|
from lms.djangoapps.courseware.tabs import get_course_tab_list
|
|
|
|
|
|
@method_decorator(transaction.non_atomic_requests, name='dispatch')
|
|
class CourseHomeMetadataView(RetrieveAPIView):
|
|
"""
|
|
**Use Cases**
|
|
|
|
Request Course metadata details for the Course Home MFE that every page needs.
|
|
|
|
**Example Requests**
|
|
|
|
GET api/course_home/v1/course_metadata/{course_key}
|
|
|
|
**Response Values**
|
|
|
|
Body consists of the following fields:
|
|
|
|
course_id: (str) The Course's id (Course Run key)
|
|
username: (str) The requesting (or masqueraded) user. Returns None for an
|
|
unauthenticated user.
|
|
is_enrolled: (bool) Indicates if the user is enrolled in the course
|
|
is_self_paced: (bool) Indicates if the course is self paced
|
|
is_staff: (bool) Indicates if the user is staff
|
|
original_user_is_staff: (bool) Indicates if the original user has staff access
|
|
Used for when masquerading to distinguish between the original requesting user
|
|
and the user being masqueraded as.
|
|
number: (str) The Course's number
|
|
org: (str) The Course's organization
|
|
tabs: List of Course Tabs to display. They are serialized as:
|
|
tab_id: (str) The tab's id
|
|
title: (str) The title of the tab to display
|
|
url: (str) The url to view the tab
|
|
title: (str) The Course's display title
|
|
celebrations: (dict) a dict of celebration data
|
|
user_timezone: (str) The timezone of the given user
|
|
can_view_certificate: Flag to determine whether or not the learner can view their course certificate.
|
|
|
|
**Returns**
|
|
|
|
* 200 on success with above fields.
|
|
* 404 if the course is not available or cannot be seen.
|
|
"""
|
|
|
|
authentication_classes = (
|
|
JwtAuthentication,
|
|
BearerAuthenticationAllowInactiveUser,
|
|
SessionAuthenticationAllowInactiveUser,
|
|
)
|
|
|
|
serializer_class = CourseHomeMetadataSerializer
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
course_key_string = kwargs.get('course_key_string')
|
|
course_key = CourseKey.from_string(course_key_string)
|
|
original_user_is_global_staff = self.request.user.is_staff
|
|
original_user_is_staff = has_access(request.user, 'staff', course_key).has_access
|
|
|
|
course = course_detail(request, request.user.username, course_key)
|
|
|
|
# We must compute course load access *before* setting up masquerading,
|
|
# else course staff (who are not enrolled) will not be able view
|
|
# their course from the perspective of a learner.
|
|
load_access = check_course_access(
|
|
course,
|
|
request.user,
|
|
'load',
|
|
check_if_enrolled=True,
|
|
check_if_authenticated=True,
|
|
apply_enterprise_checks=True,
|
|
)
|
|
|
|
_, request.user = setup_masquerade(
|
|
request,
|
|
course_key,
|
|
staff_access=original_user_is_staff,
|
|
reset_masquerade_data=True,
|
|
)
|
|
|
|
username = request.user.username if request.user.username else None
|
|
enrollment = CourseEnrollment.get_enrollment(request.user, course_key_string)
|
|
user_is_enrolled = bool(enrollment and enrollment.is_active)
|
|
|
|
# User locale settings
|
|
user_timezone_locale = user_timezone_locale_prefs(request)
|
|
user_timezone = user_timezone_locale['user_timezone']
|
|
|
|
browser_timezone = self.request.query_params.get('browser_timezone', None)
|
|
celebrations = get_celebrations_dict(
|
|
request.user, enrollment, course, user_timezone if not None else browser_timezone
|
|
)
|
|
|
|
# Record course goals user activity for (web) learning mfe course tabs
|
|
UserActivity.record_user_activity(request.user, course_key)
|
|
|
|
course_modes = CourseMode.modes_for_course(course_key, include_expired=True, only_selectable=False)
|
|
|
|
data = {
|
|
'course_id': course.id,
|
|
'username': username,
|
|
'studio_access': has_cms_access(request.user, course_key),
|
|
'is_staff': has_access(request.user, 'staff', course_key).has_access,
|
|
'original_user_is_staff': original_user_is_staff,
|
|
'number': course.display_number_with_default,
|
|
'org': course.display_org_with_default,
|
|
'start': course.start,
|
|
'tabs': get_course_tab_list(request.user, course),
|
|
'title': course.display_name_with_default,
|
|
'is_self_paced': getattr(course, 'self_paced', False),
|
|
'is_enrolled': user_is_enrolled,
|
|
'course_access': load_access.to_json(),
|
|
'celebrations': celebrations,
|
|
'user_timezone': user_timezone,
|
|
'can_view_certificate': certificates_viewable_for_course(course),
|
|
'course_modes': course_modes,
|
|
'is_new_discussion_sidebar_view_enabled': new_discussion_sidebar_view_is_enabled(course_key),
|
|
}
|
|
context = self.get_serializer_context()
|
|
context['course'] = course
|
|
context['course_overview'] = course
|
|
context['enrollment'] = enrollment
|
|
serializer = self.get_serializer_class()(data, context=context)
|
|
return Response(serializer.data)
|