Exemplo n.º 1
0
    def delete(self, request, *args, **kwargs):  # pylint: disable=too-many-locals
        """
        Allows to safely remove an edxapp User.

        For example:

        **Requests**:
            DELETE <domain>/eox-core/support-api/v1/user/

        **Request body**:
            {
                "case_id": Optional. ID of the support case for naming the retired user Email
            }

        **Response values**:
            - 200: Success, user has multiple signup sources and the one that matches the current site
                    has been deleted.
            - 202: Success, user has a unique signup source and has been safely removed from the platform.
            - 400: Bad request, invalid case_id or user has no signup source on the request site.
        """
        query = self.get_user_query(request)

        serializer = WrittableEdxappRemoveUserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data
        data["site"] = get_current_site(request)
        data["user"] = get_edxapp_user(**query)

        message, status = delete_edxapp_user(**data)

        return Response(message, status=status)
Exemplo n.º 2
0
def get_user(**kwargs):
    """Function used to get users."""
    user_id = kwargs.get("target_id")
    if getattr(settings, "EOX_TAGGING_SKIP_VALIDATIONS",
               False):  # Skip these validations while testing
        return User.objects.get(username=user_id)

    site = crum.get_current_request().site
    user = get_edxapp_user(username=user_id, site=site)
    return user
Exemplo n.º 3
0
    def delete(self, request, *args, **kwargs):
        """
        Delete enrollment on edxapp
        """
        user_query = self.get_user_query(request)
        user = get_edxapp_user(**user_query)

        course_id = self.query_params.get('course_id', None)

        if not course_id:
            raise ValidationError(detail='You have to provide a course_id')

        delete_enrollment(user=user, course_id=course_id)
        return Response(status=status.HTTP_204_NO_CONTENT)
Exemplo n.º 4
0
    def single_enrollment_update(self, *args, **kwargs):
        """
        Handle one update at the time
        """
        user_query = self.get_user_query(None, query_params=kwargs)
        user = get_edxapp_user(**user_query)

        course_id = kwargs.pop('course_id', None)
        if not course_id:
            raise ValidationError(
                detail='You have to provide a course_id for updates')
        mode = kwargs.pop('mode', None)

        return update_enrollment(user, course_id, mode, **kwargs)
Exemplo n.º 5
0
    def __validate_user_integrity(self, object_name):
        """
        Function that validates existence of user.

        Arguments:
            - object_name: name of the object to validate. It can be: target_object or owner_object
        """
        request = crum.get_current_request()
        data = {
            "username": self.instance.get_attribute(
                object_name).username,  # User needs to have username
            "site": request.site
        }
        try:
            get_edxapp_user(**data)

        except Exception:
            raise ValidationError(
                "EOX_TAGGING | Could not find ID: {id} for relation '{name}'".
                format(
                    id=self.instance.get_attribute(object_name).id,
                    name=object_name,
                ))
Exemplo n.º 6
0
    def get(self, request, *args, **kwargs):
        """
        Retrieve an user from edxapp
        """
        query = self.get_user_query(request)
        user = get_edxapp_user(**query)
        admin_fields = getattr(settings, 'ACCOUNT_VISIBILITY_CONFIGURATION',
                               {}).get('admin_fields', {})
        serialized_user = EdxappUserReadOnlySerializer(
            user, custom_fields=admin_fields, context={'request': request})
        response_data = serialized_user.data
        # Show a warning if the request is providing email and username
        # to let the client know we're giving priority to the username
        if 'username' and 'email' in self.query_params:
            response_data[
                'warning'] = 'The username prevails over the email when both are provided to get the user.'

        return Response(response_data)
Exemplo n.º 7
0
    def patch(self, request, *args, **kwargs):
        """
        Allows to safely update an Edxapp user's Username along with the
        forum associated User.

        For now users that have different signup sources cannot be updated.

        For example:

        **Requests**:
            PATCH <domain>/eox-core/support-api/v1/replace-username/

        **Request body**
            {
                "new_username": "******"
            }

        **Response values**
            User serialized.
        """
        query = self.get_user_query(request)
        user = get_edxapp_user(**query)
        data = request.data

        with transaction.atomic():
            serializer = WrittableEdxappUsernameSerializer(user, data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()

            data = serializer.validated_data
            data["user"] = user

            # Update user in cs_comments_service forums
            replace_username_cs_user(**data)

        admin_fields = getattr(settings, "ACCOUNT_VISIBILITY_CONFIGURATION", {}).get(
            "admin_fields", {}
        )
        serialized_user = EdxappUserReadOnlySerializer(
            user, custom_fields=admin_fields, context={"request": request}
        )
        return Response(serialized_user.data)
Exemplo n.º 8
0
    def single_enrollment_create(self, *args, **kwargs):
        """
        Handle one create at the time
        """
        user_query = self.get_user_query(None, query_params=kwargs)
        user = get_edxapp_user(**user_query)

        enrollments, msgs = create_enrollment(user, **kwargs)
        # This logic block is needed to convert a single bundle_id enrollment in a list
        # of course_id enrollments which are appended to the response individually
        if not isinstance(enrollments, list):
            enrollments = [enrollments]
            msgs = [msgs]
        response_data = []
        for enrollment, msg in zip(enrollments, msgs):
            data = EdxappCourseEnrollmentSerializer(enrollment).data
            if msg:
                data["messages"] = msg
            response_data.append(data)

        return response_data
Exemplo n.º 9
0
    def get(self, request, *args, **kwargs):
        """
        Get enrollments on edxapp
        """
        user_query = self.get_user_query(request)
        user = get_edxapp_user(**user_query)

        course_id = self.query_params.get('course_id', None)

        if not course_id:
            raise ValidationError(detail='You have to provide a course_id')

        enrollment_query = {
            'username': user.username,
            'course_id': course_id,
        }
        enrollment, errors = get_enrollment(**enrollment_query)

        if errors:
            raise NotFound(detail=errors)
        response = EdxappCourseEnrollmentSerializer(enrollment).data
        return Response(response)
Exemplo n.º 10
0
    def patch(self, request, *args, **kwargs):
        """
        Partially update a user from edxapp. Not all the fields can be updated, just the ones thought as `safe`.

        For example:

        **Requests**:
            PATCH <domain>/eox-core/api/v1/user/

        **Request body**
            {
                "email"=<USER_EMAIL>,
                "is_active": true,
                "password": "******"
            }

        **Response values**
            User serialized.
        """
        # Pop identification
        data = request.data.copy()
        query_params = {
            "email": data.pop("email", None),
        }
        query = self.get_user_query(request, query_params=query_params)
        user = get_edxapp_user(**query)

        serializer = WrittableEdxappUserSerializer(user,
                                                   data=data,
                                                   partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        admin_fields = getattr(settings, 'ACCOUNT_VISIBILITY_CONFIGURATION',
                               {}).get('admin_fields', {})
        serialized_user = EdxappUserReadOnlySerializer(
            user, custom_fields=admin_fields, context={'request': request})
        return Response(serialized_user.data)
Exemplo n.º 11
0
    def get(self, request, *args, **kwargs):
        """
        Retrieves enrollment information given a user and a course_id

        **Example Requests**

            GET /eox-core/api/v1/enrollment/?username=johndoe&
            course_id=course-v1:edX+DemoX+Demo_Course

            Request data: {
              "username": "******",
              "course_id": "course-v1:edX+DemoX+Demo_Course",
            }

        **Returns**

        - 200: Success, enrollment found.
        - 400: Bad request, missing course_id or either email or username
        - 404: User or course not found
        """
        user_query = self.get_user_query(request)
        user = get_edxapp_user(**user_query)

        course_id = self.query_params.get("course_id", None)

        if not course_id:
            raise ValidationError(detail="You have to provide a course_id")

        enrollment_query = {
            "username": user.username,
            "course_id": course_id,
        }
        enrollment, errors = get_enrollment(**enrollment_query)

        if errors:
            raise NotFound(detail=errors)
        response = EdxappCourseEnrollmentSerializer(enrollment).data
        return Response(response)
Exemplo n.º 12
0
    def delete(self, request, *args, **kwargs):
        """
        Delete enrollment on edxapp

        **Example Requests**

            DELETE /eox-core/api/v1/enrollment/

            Request data: {
              "username": "******",
              "course_id": "course-v1:edX+DemoX+Demo_Course",
            }
        """
        user_query = self.get_user_query(request)
        user = get_edxapp_user(**user_query)

        course_id = self.query_params.get("course_id", None)

        if not course_id:
            raise ValidationError(detail="You have to provide a course_id")

        delete_enrollment(user=user, course_id=course_id)
        return Response(status=status.HTTP_204_NO_CONTENT)
Exemplo n.º 13
0
    def patch(self, request, *args, **kwargs):
        """
        Partially updates a user from edxapp.

        **Example Requests**

            PATCH /eox-core/api/v1/update-user/

            Request data: {
                "email": "*****@*****.**",
                "fullname": "John Doe R",
                "password": "******",
            }


        **Parameters**

        - `email` (**required**, string, _body_):
            The email used to identify the user. Use either username or email.

        - `username` (**required**, string, _body_):
            The username used to identify the user. Use either username or email.

        - `password` (**optional**, string, _body_):
            The new password of the user.

        - `fullname` (**optional**, string, _body_):
            The full name to be assigned.

        - `is_active` (**optional**, boolean, _body_):
            Flag indicating if the user is active on the platform.

        - Not all the fields can be updated, just the ones thought as 'safe', such as: "is_active", "password", "fullname"

        - By default, these are the 'safe' extra registration fields: "mailing_address", "year_of_birth", "gender", "level_of_education",
        "city", "country", "goals", "bio" and "phone_number".

        If you have extra registration fields configured in your settings or extended_profile fields, and you want to update them, you can send them along with the rest of the parameters.
        For example:

            {
                "email": "*****@*****.**",
                "fullname": "John Doe R",
                "password": "******",
                "gender": "f",
                "country": "US",
            }

        **Response details**

        - `username (str)`: Username of the edxapp user
        - `is_active (str)`: Indicates if the user is active on the platform
        - `email (str)`: Email of the user
        - `gender (str)`: Gender of the user
        - `date_joined (str)`: Date for when the user was registered in the platform
        - `name (str)`: Fullname of the user
        - `country (str)`: Country of the user
        - `level_of_education (str)`: Level of education of the user
        - `year_of_birth (int)`: Year of birth of the user
        - `bio (str)`: Bio of the user
        - `goals (str)`: Goals of the user
        - `extended_profile (list)`: List of dictionaries that contains the user-profile meta fields
            - `field_name (str)`: Name of the extended profile field
            - `field_value (str)`: Value of the extended profile field
        - `mailing_address (str)`
        - `social_links (List)`: List that contains the social links of the user, if any.
        - `account_privacy (str)`: Indicates the account privacy type
        - `state (str)`: State (only for US)
        - `secondary_email (str)`: Secondary email of the user
        - `profile_image (dictionary)`:
            - `has_image (Bool)`: Indicates if user has profile image
            - `image_url_medium (str)`: Url of the profile image in medium size
            - `image_url_small (str)`: Url of the profile image in small size
            - `image_url_full (str)`: Url of the profile image in full size,
            - `image_url_large (str)`: Url of the profile image in large size
        - `secondary_email_enabled (Bool)`: Indicates if the secondary email is enable
        - `phone_number (str)`: Phone number of the user
        - `requires_parental_consent (Bool)`: Indicates whether parental consent is required for the user

        **Returns**

        - 200: Success, user updated.
        - 400: Bad request, a required field is now null or has been entered with the wrong format.
        - 401: Unauthorized user to make the request.
        - 404: User not found
        """
        # Pop identification
        data = request.data.copy()
        query_params = {
            "email": data.pop("email", None),
            "username": data.pop("username", None),
        }
        query = self.get_user_query(request, query_params=query_params)
        user = get_edxapp_user(**query)

        serializer = WrittableEdxappUserSerializer(user,
                                                   data=data,
                                                   partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        admin_fields = getattr(settings, "ACCOUNT_VISIBILITY_CONFIGURATION",
                               {}).get("admin_fields", {})
        serialized_user = EdxappUserReadOnlySerializer(
            user, custom_fields=admin_fields, context={"request": request})
        return Response(serialized_user.data)
Exemplo n.º 14
0
    def get(self, request, *args, **kwargs):
        """
        Retrieves information about an edxapp user,
        given an email or a username.

        The username prevails over the email when both are provided to get the user.

        **Example Requests**

            GET /eox-core/api/v1/user/?username=johndoe

            Query parameters: {
              "username": "******",
            }

        **Response details**

        - `username (str)`: Username of the edxapp user
        - `is_active (str)`: Indicates if the user is active on the platform
        - `email (str)`: Email of the user
        - `gender (str)`: Gender of the user
        - `date_joined (str)`: Date for when the user was registered in the platform
        - `name (str)`: Fullname of the user
        - `country (str)`: Country of the user
        - `level_of_education (str)`: Level of education of the user
        - `year_of_birth (int)`: Year of birth of the user
        - `bio (str)`: Bio of the user
        - `goals (str)`: Goals of the user
        - `extended_profile (list)`: List of dictionaries that contains the user-profile meta fields
            - `field_name (str)`: Name of the extended profile field
            - `field_value (str)`: Value of the extended profile field
        - `mailing_address (str)`
        - `social_links (List)`: List that contains the social links of the user, if any.
        - `account_privacy (str)`: Indicates the account privacy type
        - `state (str)`: State (only for US)
        - `secondary_email (str)`: Secondary email of the user
        - `profile_image (dictionary)`:
            - `has_image (Bool)`: Indicates if user has profile image
            - `image_url_medium (str)`: Url of the profile image in medium size
            - `image_url_small (str)`: Url of the profile image in small size
            - `image_url_full (str)`: Url of the profile image in full size,
            - `image_url_large (str)`: Url of the profile image in large size
        - `secondary_email_enabled (Bool)`: Indicates if the secondary email is enable
        - `phone_number (str)`: Phone number of the user
        - `requires_parental_consent (Bool)`: Indicates whether parental consent is required for the user

        **Returns**

        - 200: Success, user found.
        - 400: Bad request, missing either email or username
        - 401: Unauthorized user to make the request.
        - 404: User not found
        """
        query = self.get_user_query(request)
        user = get_edxapp_user(**query)
        admin_fields = getattr(settings, "ACCOUNT_VISIBILITY_CONFIGURATION",
                               {}).get("admin_fields", {})
        serialized_user = EdxappUserReadOnlySerializer(
            user, custom_fields=admin_fields, context={"request": request})
        response_data = serialized_user.data
        # Show a warning if the request is providing email and username
        # to let the client know we're giving priority to the username
        if "username" and "email" in self.query_params:
            response_data[
                "warning"] = "The username prevails over the email when both are provided to get the user."

        return Response(response_data)
Exemplo n.º 15
0
    def get(self, request):
        """
        Retrieves Grades information for given a user and course_id

        **Example Requests**

            GET /eox-core/api/v1/grade/?username=johndoe&course_id=course-v1:edX+DemoX+Demo_Course

            Request data: {
              "username": "******",
              "course_id": "course-v1:edX+DemoX+Demo_Course",
            }

        **Response details**

        - `earned_grade`: Final user score for the course.
        - `section_breakdown` (**optional**): Details of each grade subsection.
            - `attempted`: Whether the learner attempted the assignment.
            - `assignment_type`: General category of the assignment.
            - `percent`: Grade obtained by the user on this subsection.
            - `score_earned`: The score a user earned on this subsection.
            - `score_possible`: Highest possible score a user can earn on this subsection.
            - `subsection_name`: Name of the subsection.
        - `grading_policy` (**optional**): Course grading policy.
            - `grade_cutoff`: Score needed to reach each grade.
            - `grader`: Details of each assignment type used by the Grader.
                - `assignment_type`: General category of the assignment.
                - `count`: Number of assignments of this type.
                - `dropped`: The number of assignments of this type that the grader will drop. The grader will drop the lowest-scored assignments first.
                - `weight`: Weight of this type of assignment towards the final grade.

        More information about grading can be found in the
        [edX documentation](https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/latest/student_progress/course_grades.html).

        **Returns**

        - 200: Success.
        - 400: Bad request, missing course_id or either email or username.
        - 404: User, course or enrollment not found.
        """
        user_query = self.get_user_query(request)
        user = get_edxapp_user(**user_query)

        course_id = self.query_params.get("course_id", None)
        detailed = self.query_params.get("detailed", False)
        grading_policy = self.query_params.get("grading_policy", False)

        if not course_id:
            raise ValidationError(detail="You have to provide a course_id")

        _, errors = get_enrollment(username=user.username, course_id=course_id)

        if errors:
            raise NotFound(errors)

        grade_factory = get_course_grade_factory()
        course_key = get_valid_course_key(course_id)
        course = get_courseware_courses().get_course_by_id(course_key)
        course_grade = grade_factory().read(user, course)
        response = {"earned_grade": course_grade.percent}

        if detailed in ("True", "true", "on", "1"):
            breakdown = self._section_breakdown(course_grade.subsection_grades)
            response["section_breakdown"] = breakdown
        if grading_policy in ("True", "true", "on", "1"):
            response["grading_policy"] = course.grading_policy

        return Response(EdxappGradeSerializer(response).data)