<commit_before>"""
Course API Views
"""

import json

from opaque_keys.edx.keys import CourseKey, UsageKey
from rest_framework.generics import RetrieveAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from lms.djangoapps.course_api.api import course_detail
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.courses import allow_public_access
from lms.djangoapps.courseware.module_render import get_module_by_usage_id
from student.models import CourseEnrollment

from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin
from xmodule.course_module import COURSE_VISIBILITY_PUBLIC

from .serializers import CourseInfoSerializer


class CoursewareInformation(RetrieveAPIView):
    """
    **Use Cases**

        Request details for a course

    **Example Requests**

        GET /api/courseware/course/{course_key}

    **Response Values**

        Body consists of the following fields:

        * effort: A textual description of the weekly hours of effort expected
            in the course.
        * end: Date the course ends, in ISO 8601 notation
        * enrollment_end: Date enrollment ends, in ISO 8601 notation
        * enrollment_start: Date enrollment begins, in ISO 8601 notation
        * id: A unique identifier of the course; a serialized representation
            of the opaque key identifying the course.
        * media: An object that contains named media items.  Included here:
            * course_image: An image to show for the course.  Represented
              as an object with the following fields:
                * uri: The location of the image
        * name: Name of the course
        * number: Catalog number of the course
        * org: Name of the organization that owns the course
        * short_description: A textual description of the course
        * start: Date the course begins, in ISO 8601 notation
        * start_display: Readably formatted start of the course
        * start_type: Hint describing how `start_display` is set. One of:
            * `"string"`: manually set by the course author
            * `"timestamp"`: generated from the `start` timestamp
            * `"empty"`: no start date is specified
        * pacing: Course pacing. Possible values: instructor, self
        * tabs: Course tabs
        * enrollment: Enrollment status of authenticated user
            * mode: `audit`, `verified`, etc
            * is_active: boolean
        * user_has_access: Whether the user can view the course

    **Parameters:**

        requested_fields (optional) comma separated list:
            If set, then only those fields will be returned.

    **Returns**

        * 200 on success with above fields.
        * 400 if an invalid parameter was sent or the username was not provided
          for an authenticated request.
        * 403 if a user who does not have permission to masquerade as
          another user specifies a username other than their own.
        * 404 if the course is not available or cannot be seen.
    """

    serializer_class = CourseInfoSerializer

    def get_object(self):
        """
        Return the requested course object, if the user has appropriate
        permissions.
        """

        overview = course_detail(
            self.request,
            self.request.user.username,
            CourseKey.from_string(self.kwargs['course_key_string']),
        )
        if self.request.user.is_anonymous:
            mode = None
            is_active = False
        else:
            mode, is_active = CourseEnrollment.enrollment_mode_for_user(
                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
        return overview
<commit_msg>fix: Improving access check in CoursewareInformation view<commit_after>"""
Course API Views
"""

import json

from opaque_keys.edx.keys import CourseKey, UsageKey
from rest_framework.generics import RetrieveAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from lms.djangoapps.course_api.api import course_detail
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.courses import allow_public_access
from lms.djangoapps.courseware.module_render import get_module_by_usage_id
from student.models import CourseEnrollment

from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin
from xmodule.course_module import COURSE_VISIBILITY_PUBLIC

from .serializers import CourseInfoSerializer


class CoursewareInformation(RetrieveAPIView):
    """
    **Use Cases**

        Request details for a course

    **Example Requests**

        GET /api/courseware/course/{course_key}

    **Response Values**

        Body consists of the following fields:

        * effort: A textual description of the weekly hours of effort expected
            in the course.
        * end: Date the course ends, in ISO 8601 notation
        * enrollment_end: Date enrollment ends, in ISO 8601 notation
        * enrollment_start: Date enrollment begins, in ISO 8601 notation
        * id: A unique identifier of the course; a serialized representation
            of the opaque key identifying the course.
        * media: An object that contains named media items.  Included here:
            * course_image: An image to show for the course.  Represented
              as an object with the following fields:
                * uri: The location of the image
        * name: Name of the course
        * number: Catalog number of the course
        * org: Name of the organization that owns the course
        * short_description: A textual description of the course
        * start: Date the course begins, in ISO 8601 notation
        * start_display: Readably formatted start of the course
        * start_type: Hint describing how `start_display` is set. One of:
            * `"string"`: manually set by the course author
            * `"timestamp"`: generated from the `start` timestamp
            * `"empty"`: no start date is specified
        * pacing: Course pacing. Possible values: instructor, self
        * tabs: Course tabs
        * enrollment: Enrollment status of authenticated user
            * mode: `audit`, `verified`, etc
            * is_active: boolean
        * user_has_access: Whether the user can view the course

    **Parameters:**

        requested_fields (optional) comma separated list:
            If set, then only those fields will be returned.

    **Returns**

        * 200 on success with above fields.
        * 400 if an invalid parameter was sent or the username was not provided
          for an authenticated request.
        * 403 if a user who does not have permission to masquerade as
          another user specifies a username other than their own.
        * 404 if the course is not available or cannot be seen.
    """

    serializer_class = CourseInfoSerializer

    def _check_access(self, user, overview):
        if has_access(user, 'staff', overview):
            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

        has_public_access = allow_public_access(overview, [COURSE_VISIBILITY_PUBLIC])
        if user.is_anonymous and not has_public_access:
            return False

        if not CourseEnrollment.is_enrolled(user, overview.id) and not has_public_access:
            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
        permissions.
        """

        overview = course_detail(
            self.request,
            self.request.user.username,
            CourseKey.from_string(self.kwargs['course_key_string']),
        )

        if self.request.user.is_anonymous:
            mode = None
            is_active = False
        else:
            mode, is_active = CourseEnrollment.enrollment_mode_for_user(
                overview.effective_user,
                overview.id
            )
        overview.enrollment = {'mode': mode, 'is_active': is_active}

        overview.can_load_course = self._check_access(self.request.user, overview)
        overview.is_staff = has_access(self.request.user, 'staff', overview).has_access

        overview.user_has_access = overview.can_load_course # TODO: TNL-7053 Legacy: Delete once ready to contract
        overview.user_has_staff_access = overview.is_staff # TODO: TNL-7053 Legacy: Delete once ready to contract

        return overview

{'fraction_non_alphanumeric': 0.06059609905763752, 'fraction_numerical': 0.007012930089853167, 'mean_word_length': 2.5848389630793402, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6030552', 'n_tokens_mistral': 2419, 'n_tokens_neox': 2269, 'n_words': 861}