Merge pull request #23585 from edx/djoy/course_metadata_access_check

fix: Improving access check in CoursewareInformation view
This commit is contained in:
David Joy
2020-04-06 13:05:39 -04:00
committed by GitHub
2 changed files with 35 additions and 9 deletions

View File

@@ -83,11 +83,15 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract-
start_type = serializers.CharField()
pacing = serializers.CharField()
enrollment = serializers.DictField()
user_has_access = serializers.BooleanField()
user_has_staff_access = serializers.BooleanField()
tabs = serializers.SerializerMethodField()
verified_mode = serializers.SerializerMethodField()
show_calculator = serializers.BooleanField()
is_staff = serializers.BooleanField()
can_load_courseware = serializers.BooleanField()
# TODO: TNL-7053 Legacy: Delete these two once ready to contract
user_has_access = serializers.BooleanField()
user_has_staff_access = serializers.BooleanField()
def __init__(self, *args, **kwargs):
"""

View File

@@ -80,6 +80,26 @@ class CoursewareInformation(RetrieveAPIView):
serializer_class = CourseInfoSerializer
def _check_access(self, user, overview, is_staff):
if is_staff:
return True
# We can only trust has_access in its false case because it doesn't check everything we
# need to check.
if not has_access(user, 'load', overview):
return False
# Anonymous or unenrolled users
if user.is_anonymous or not CourseEnrollment.is_enrolled(user, overview.id):
# do not have access if the course is not public
if not allow_public_access(overview, [COURSE_VISIBILITY_PUBLIC]):
return False
# if is_survey_required_and_unanswered(user, course):
# TODO: This.
return True
def get_object(self):
"""
Return the requested course object, if the user has appropriate
@@ -91,6 +111,7 @@ class CoursewareInformation(RetrieveAPIView):
self.request.user.username,
CourseKey.from_string(self.kwargs['course_key_string']),
)
if self.request.user.is_anonymous:
mode = None
is_active = False
@@ -99,14 +120,15 @@ class CoursewareInformation(RetrieveAPIView):
overview.effective_user,
overview.id
)
overview.enrollment = {'mode': mode, 'is_active': is_active}
if not is_active:
user_has_access = allow_public_access(overview, [COURSE_VISIBILITY_PUBLIC])
else:
user_has_access = True
overview.user_has_access = user_has_access
overview.user_has_staff_access = has_access(self.request.user, 'staff', overview).has_access
overview.is_staff = has_access(self.request.user, 'staff', overview).has_access
overview.can_load_courseware = self._check_access(self.request.user, overview, overview.is_staff)
# TODO: TNL-7053 Legacy: Delete these two once ready to contract
overview.user_has_access = overview.can_load_courseware
overview.user_has_staff_access = overview.is_staff
return overview
def get_serializer_context(self):