Add optional role parameter to course API endpoint. (#21059)
* Add optional role parameter to course API endpoint. * fixup! Add optional role parameter to course API endpoint.
This commit is contained in:
@@ -4,14 +4,19 @@ Course API
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser, User
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
import search
|
||||
import six
|
||||
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.courses import (
|
||||
get_course_overview_with_access,
|
||||
get_courses,
|
||||
get_permission_for_course_about
|
||||
)
|
||||
from openedx.core.lib.api.view_utils import LazySequence
|
||||
|
||||
from .permissions import can_view_courses_for_username
|
||||
|
||||
@@ -57,7 +62,54 @@ def course_detail(request, username, course_key):
|
||||
)
|
||||
|
||||
|
||||
def list_courses(request, username, org=None, filter_=None):
|
||||
def _filter_by_role(course_queryset, user, roles):
|
||||
"""
|
||||
Filters a course queryset by the roles for which the user has access.
|
||||
"""
|
||||
# Global staff have access to all courses. Filter course roles for non-global staff only.
|
||||
if not user.is_staff:
|
||||
if roles:
|
||||
for role in roles:
|
||||
# Filter the courses again to return only the courses for which the user has each specified role.
|
||||
course_queryset = LazySequence(
|
||||
(
|
||||
course for course in course_queryset
|
||||
if has_access(user, role, course.id)
|
||||
),
|
||||
est_len=len(course_queryset)
|
||||
)
|
||||
return course_queryset
|
||||
|
||||
|
||||
def _filter_by_search(course_queryset, search_term):
|
||||
"""
|
||||
Filters a course queryset by the specified search term.
|
||||
"""
|
||||
if not settings.FEATURES['ENABLE_COURSEWARE_SEARCH'] or not search_term:
|
||||
return course_queryset
|
||||
|
||||
# Return all the results, 10K is the maximum allowed value for ElasticSearch.
|
||||
# We should use 0 after upgrading to 1.1+:
|
||||
# - https://github.com/elastic/elasticsearch/commit/8b0a863d427b4ebcbcfb1dcd69c996c52e7ae05e
|
||||
results_size_infinity = 10000
|
||||
|
||||
search_courses = search.api.course_discovery_search(
|
||||
search_term,
|
||||
size=results_size_infinity,
|
||||
)
|
||||
|
||||
search_courses_ids = {course['data']['id'] for course in search_courses['results']}
|
||||
|
||||
return LazySequence(
|
||||
(
|
||||
course for course in course_queryset
|
||||
if six.text_type(course.id) in search_courses_ids
|
||||
),
|
||||
est_len=len(course_queryset)
|
||||
)
|
||||
|
||||
|
||||
def list_courses(request, username, org=None, roles=None, filter_=None, search_term=None):
|
||||
"""
|
||||
Yield all available courses.
|
||||
|
||||
@@ -78,12 +130,21 @@ def list_courses(request, username, org=None, filter_=None):
|
||||
If specified, visible `CourseOverview` objects are filtered
|
||||
such that only those belonging to the organization with the provided
|
||||
org code (e.g., "HarvardX") are returned. Case-insensitive.
|
||||
roles (list of strings):
|
||||
If specified, visible `CourseOverview` objects are filtered
|
||||
such that only those for which the user has the specified role(s)
|
||||
are returned. Multiple role parameters can be specified.
|
||||
filter_ (dict):
|
||||
If specified, visible `CourseOverview` objects are filtered
|
||||
by the given key-value pairs.
|
||||
search_term (string):
|
||||
Search term to filter courses (used by ElasticSearch).
|
||||
|
||||
Return value:
|
||||
Yield `CourseOverview` objects representing the collection of courses.
|
||||
"""
|
||||
user = get_effective_user(request.user, username)
|
||||
return get_courses(user, org=org, filter_=filter_)
|
||||
course_qs = get_courses(user, org=org, filter_=filter_)
|
||||
course_qs = _filter_by_role(course_qs, user, roles)
|
||||
course_qs = _filter_by_search(course_qs, search_term)
|
||||
return course_qs
|
||||
|
||||
Reference in New Issue
Block a user