<commit_before>"""
API to update user enrollments
"""
import json

from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils.decorators import method_decorator
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_oauth.authentication import OAuth2Authentication

from courseware.courses import get_course_by_id
from lms.djangoapps.instructor.enrollment import (
    enroll_email,
    get_email_params,
    get_user_email_language,
    unenroll_email,
)
from openedx.core.djangoapps.cors_csrf.decorators import ensure_csrf_cookie_cross_domain
from openedx.core.djangoapps.user_api.helpers import require_post_params
from openedx.core.lib.api.permissions import ApiKeyHeaderPermission
from openedx.core.lib.api.permissions import ApiKeyHeaderPermissionIsAuthenticated
from student.auth import user_has_role
from student.roles import CourseStaffRole
from enrollment.views import ApiKeyPermissionMixIn
from openedx.stanford.common.djangoapps.enrollment.data import get_roster


class EnrollmentRosterView(APIView, ApiKeyPermissionMixIn):
    """
    Read roster for a particular course. (contains PII)
    """
    authentication_classes = OAuth2Authentication,
    permission_classes = ApiKeyHeaderPermissionIsAuthenticated,

    @method_decorator(ensure_csrf_cookie_cross_domain)
    def get(self, request, course_id=None):
        """
        List a course's enrollment roster; requires staff access

        **Example Request**
            GET /api/enrollment/v1/roster/course-v1:foo+bar+foobar
            { }
        """
        try:
            course_key = CourseKey.from_string(course_id)
        except InvalidKeyError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid or missing course_id',
                },
            )
        if not user_has_role(request.user, CourseStaffRole(course_key)):
            return Response(
                status=status.HTTP_403_FORBIDDEN,
                data={"message": u"User does not have permission to view roster for [{course_id}].".format(course_id=course_id)},
            )
        roster = get_roster(course_id)
        return Response(data=json.dumps({'roster': roster}))

    def put(self, request, course_id):
        """
        Enroll a user in a course; requires staff access

        **Example Request**
            PUT /api/enrollment/v1/roster/course-v1:foo+bar+foobar
            {
                'email': '<EMAIL>',
                'email_students': false,
                'auto_enroll': true
            }
        """
        try:
            course_key = CourseKey.from_string(course_id)
        except InvalidKeyError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid or missing course_id',
                },
            )
        if not user_has_role(request.user, CourseStaffRole(course_key)):
            return Response(
                status=status.HTTP_403_FORBIDDEN,
                data={
                    'message': u'User does not have permission to update enrollment for [{course_id}].'.format(
                        course_id=course_id,
                    ),
                },
            )
        email = request.data.get('email')
        try:
            validate_email(email)
        except ValidationError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid email address',
                },
            )
        email_students = request.data.get('email_students', False) in ['true', 'True', True]
        auto_enroll = request.data.get('auto_enroll', False) in ['true', 'True', True]
        email_params = {}
        language = None
        if email_students:
            course = get_course_by_id(course_key)
            email_params = get_email_params(course, auto_enroll)
            if User.objects.filter(email=email).exists():
                user = User.objects.get(email=email)
                language = get_user_email_language(user)
        enroll_email(
            course_key, email, auto_enroll, email_students, email_params, language=language
        )
        return Response(status=status.HTTP_204_NO_CONTENT)

    def delete(self, request, course_id):
        """
        Unenroll a user from a course; requires staff access

        **Example Request**
            DELETE /api/enrollment/v1/roster/course-v1:foo+bar+foobar
            {
                'email': '<EMAIL>',
                'email_students': false,
                'auto_enroll': true
            }
        """
        try:
            course_key = CourseKey.from_string(course_id)
        except InvalidKeyError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid or missing course_id',
                },
            )
        if not user_has_role(request.user, CourseStaffRole(course_key)):
            return Response(
                status=status.HTTP_403_FORBIDDEN,
                data={
                    'message': u'User does not have permission to update enrollment for [{course_id}].'.format(
                        course_id=course_id,
                    ),
                },
            )
        email = request.data.get('email')
        try:
            validate_email(email)
        except ValidationError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid email address',
                },
            )
        email_students = request.data.get('email_students', False) in ['true', 'True', True]
        auto_enroll = request.data.get('auto_enroll', False) in ['true', 'True', True]
        email_params = {}
        language = None
        if email_students:
            course = get_course_by_id(course_key)
            email_params = get_email_params(course, auto_enroll)
            if User.objects.filter(email=email).exists():
                user = User.objects.get(email=email)
                language = get_user_email_language(user)
        unenroll_email(
            course_key, email, email_students, email_params, language=language
        )
        return Response(status=status.HTTP_204_NO_CONTENT)<commit_msg>Efficiency improvement for EnrollmentRosterView and helper method.<commit_after>"""
API to update user enrollments
"""
import json

from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils.decorators import method_decorator
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_oauth.authentication import OAuth2Authentication

from courseware.courses import get_course_by_id
from lms.djangoapps.instructor.enrollment import (
    enroll_email,
    get_email_params,
    get_user_email_language,
    unenroll_email,
)
from openedx.core.djangoapps.cors_csrf.decorators import ensure_csrf_cookie_cross_domain
from openedx.core.djangoapps.user_api.helpers import require_post_params
from openedx.core.lib.api.permissions import ApiKeyHeaderPermission
from openedx.core.lib.api.permissions import ApiKeyHeaderPermissionIsAuthenticated
from student.auth import user_has_role
from student.roles import CourseStaffRole
from enrollment.views import ApiKeyPermissionMixIn
from openedx.stanford.common.djangoapps.enrollment.data import get_roster


class EnrollmentRosterView(APIView, ApiKeyPermissionMixIn):
    """
    Read roster for a particular course. (contains PII)
    """
    authentication_classes = OAuth2Authentication,
    permission_classes = ApiKeyHeaderPermissionIsAuthenticated,

    @method_decorator(ensure_csrf_cookie_cross_domain)
    def get(self, request, course_id=None):
        """
        List a course's enrollment roster; requires staff access

        **Example Request**
            GET /api/enrollment/v1/roster/course-v1:foo+bar+foobar
            { }
        """
        try:
            course_key = CourseKey.from_string(course_id)
        except InvalidKeyError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid or missing course_id',
                },
            )
        if not user_has_role(request.user, CourseStaffRole(course_key)):
            return Response(
                status=status.HTTP_403_FORBIDDEN,
                data={"message": u"User does not have permission to view roster for [{course_id}].".format(course_id=course_id)},
            )
        roster = get_roster(course_id)
        return Response(data=json.dumps({'roster': roster}))

    def put(self, request, course_id):
        """
        Enroll a user in a course; requires staff access

        **Example Request**
            PUT /api/enrollment/v1/roster/course-v1:foo+bar+foobar
            {
                'email': '<EMAIL>',
                'email_students': false,
                'auto_enroll': true
            }
        """
        try:
            course_key = CourseKey.from_string(course_id)
        except InvalidKeyError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid or missing course_id',
                },
            )
        if not user_has_role(request.user, CourseStaffRole(course_key)):
            return Response(
                status=status.HTTP_403_FORBIDDEN,
                data={
                    'message': u'User does not have permission to update enrollment for [{course_id}].'.format(
                        course_id=course_id,
                    ),
                },
            )
        email = request.data.get('email')
        try:
            validate_email(email)
        except ValidationError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid email address',
                },
            )

        email_students, auto_enroll, email_params, language = api_params_helper(request, course_key, email)
        enroll_email(
            course_key, email, auto_enroll, email_students, email_params, language=language
        )
        return Response(status=status.HTTP_204_NO_CONTENT)

    def delete(self, request, course_id):
        """
        Unenroll a user from a course; requires staff access

        **Example Request**
            DELETE /api/enrollment/v1/roster/course-v1:foo+bar+foobar
            {
                'email': '<EMAIL>',
                'email_students': false,
                'auto_enroll': true
            }
        """
        try:
            course_key = CourseKey.from_string(course_id)
        except InvalidKeyError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid or missing course_id',
                },
            )
        if not user_has_role(request.user, CourseStaffRole(course_key)):
            return Response(
                status=status.HTTP_403_FORBIDDEN,
                data={
                    'message': u'User does not have permission to update enrollment for [{course_id}].'.format(
                        course_id=course_id,
                    ),
                },
            )
        email = request.data.get('email')
        try:
            validate_email(email)
        except ValidationError:
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data={
                    'message': u'Invalid email address',
                },
            )

        email_students, auto_enroll, email_params, language = api_params_helper(request, course_key, email)
        unenroll_email(
            course_key, email, email_students, email_params, language=language
        )
        return Response(status=status.HTTP_204_NO_CONTENT)

    def api_params_helper(self, request, course_key, email):
        """
        Helper method to get params for enroll/unenroll apis.
        """
        email_students = request.data.get('email_students', False) in ['true', 'True', True]
        auto_enroll = request.data.get('auto_enroll', True) in ['true', 'True', True]
        email_params = {}
        if email_students:
            course = get_course_by_id(course_key)
            email_params = get_email_params(course, auto_enroll)
            try:
                user = User.objects.get(email=email)
            except User.DoesNotExist:
                language = None
            else:
                language = get_user_email_language(user)
        return email_students, auto_enroll, email_params, language
{'fraction_non_alphanumeric': 0.08152092395380231, 'fraction_numerical': 0.005699715014249288, 'mean_word_length': 2.0918154416879204, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '368859', 'n_tokens_mistral': 3685, 'n_tokens_neox': 3513, 'n_words': 767}