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)
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
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)
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)
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, ))
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)
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)
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
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)
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)
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)
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)
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)
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)
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)