Esempio n. 1
0
    def test_locked_versioned_old_styleasset(self):
        """
        Test that locked assets that are versioned (old-style) are being served.
        """
        CourseEnrollment.enroll(self.non_staff_usr, self.course_key)
        self.assertTrue(
            CourseEnrollment.is_enrolled(self.non_staff_usr, self.course_key))

        self.client.login(username=self.non_staff_usr, password='******')
        resp = self.client.get(self.url_locked_versioned_old_style)
        self.assertEqual(resp.status_code, 200)
Esempio n. 2
0
 def test_cannot_enroll_if_already_enrolled(self):
     """
     Tests that a student will not be able to enroll through this view if
     they are already enrolled in the course
     """
     CourseEnrollment.enroll(self.user, self.course.id)
     self.assertTrue(CourseEnrollment.is_enrolled(self.user,
                                                  self.course.id))
     # now try to enroll that student
     response = self._enroll_through_view(self.course)
     self.assertEqual(response.status_code, 400)
Esempio n. 3
0
    def test_locked_asset_registered(self):
        """
        Test that locked assets behave appropriately in case user is logged in
        and registered for the course.
        """
        CourseEnrollment.enroll(self.non_staff_usr, self.course_key)
        assert CourseEnrollment.is_enrolled(self.non_staff_usr, self.course_key)

        self.client.login(username=self.non_staff_usr, password='******')
        resp = self.client.get(self.url_locked)
        assert resp.status_code == 200
Esempio n. 4
0
    def test_unenroll(self, use_json):
        """ Test unenrolling a user. """
        response = self.request_bulk_enroll(
            {
                'identifiers': self.enrolled_student.email,
                'action': 'unenroll',
                'email_students': False,
                'courses': self.course_key,
            },
            use_json=use_json)
        assert response.status_code == 200

        # test that the user is now unenrolled
        user = User.objects.get(email=self.enrolled_student.email)
        assert not CourseEnrollment.is_enrolled(user, self.course.id)

        # test the response data
        expected = {
            "action": "unenroll",
            "auto_enroll": False,
            "email_students": False,
            "courses": {
                self.course_key: {
                    "action":
                    "unenroll",
                    "auto_enroll":
                    False,
                    "results": [{
                        "identifier": self.enrolled_student.email,
                        "before": {
                            "enrollment": True,
                            "auto_enroll": False,
                            "user": True,
                            "allowed": False,
                        },
                        "after": {
                            "enrollment": False,
                            "auto_enroll": False,
                            "user": True,
                            "allowed": False,
                        }
                    }]
                }
            }
        }

        manual_enrollments = ManualEnrollmentAudit.objects.all()
        assert manual_enrollments.count() == 1
        assert manual_enrollments[0].state_transition == ENROLLED_TO_UNENROLLED
        res_json = json.loads(response.content.decode('utf-8'))
        assert res_json == expected

        # Check the outbox
        assert len(mail.outbox) == 0
Esempio n. 5
0
def can_access_self_blocks(requesting_user: User, course_key: CourseKey) -> AccessResponse:
    """
    Returns whether the requesting_user can access own blocks.
    """
    user_is_enrolled_or_staff = (  # pylint: disable=consider-using-ternary
        (requesting_user.id and CourseEnrollment.is_enrolled(requesting_user, course_key)) or
        has_access(requesting_user, CourseStaffRole.ROLE, course_key)
    )
    if user_is_enrolled_or_staff:
        return ACCESS_GRANTED
    return is_course_public(course_key)
Esempio n. 6
0
 def test_existing_inactive_enrollment(self):
     """
     If the user has an inactive enrollment for the course, the view should behave as if the
     user has no enrollment.
     """
     # Create an inactive enrollment
     CourseEnrollment.enroll(self.user, self.course.id)
     CourseEnrollment.unenroll(self.user, self.course.id, True)
     assert not CourseEnrollment.is_enrolled(self.user, self.course.id)
     assert get_enrollment(self.user.username,
                           str(self.course.id)) is not None
Esempio n. 7
0
    def test_embargo_restrict(self):
        # When accessing the course from an embargoed country,
        # we should be blocked.
        with restrict_course(self.course.id) as redirect_url:
            response = self._change_enrollment('enroll')
            assert response.status_code == 200
            assert response.content.decode('utf-8') == redirect_url

        # Verify that we weren't enrolled
        is_enrolled = CourseEnrollment.is_enrolled(self.user, self.course.id)
        assert not is_enrolled
Esempio n. 8
0
    def test_unenroll(self):
        # Enroll the student in the course
        CourseEnrollment.enroll(self.user, self.course.id, mode="honor")

        # Attempt to unenroll the student
        resp = self._change_enrollment('unenroll')
        self.assertEqual(resp.status_code, 200)

        # Expect that we're no longer enrolled
        self.assertFalse(
            CourseEnrollment.is_enrolled(self.user, self.course.id))
Esempio n. 9
0
    def test_user_is_not_unenrolled_on_failed_refund(
            self,
            mock_get_course_runs,
            mock_refund_entitlement,  # pylint: disable=unused-argument
            mock_is_refundable  # pylint: disable=unused-argument
    ):
        course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED)
        mock_get_course_runs.return_value = self.return_values

        url = reverse(
            self.ENTITLEMENTS_ENROLLMENT_NAMESPACE,
            args=[str(course_entitlement.uuid)]
        )
        assert course_entitlement.enrollment_course_run is None

        # Enroll the User
        data = {
            'course_run_id': str(self.course.id)
        }
        response = self.client.post(
            url,
            data=json.dumps(data),
            content_type='application/json',
        )
        course_entitlement.refresh_from_db()

        assert response.status_code == 201
        assert CourseEnrollment.is_enrolled(self.user, self.course.id)

        # Unenroll with Revoke for refund
        revoke_url = url + '?is_refund=true'
        response = self.client.delete(
            revoke_url,
            content_type='application/json',
        )
        assert response.status_code == 500

        course_entitlement.refresh_from_db()
        assert CourseEnrollment.is_enrolled(self.user, self.course.id)
        assert course_entitlement.enrollment_course_run is not None
        assert course_entitlement.expired_at is None
Esempio n. 10
0
 def test_no_duplicate_emails_unenrolled_staff(self):
     """
     Test that no duplicate emails are sent to a course staff that is
     not enrolled in the course, but is enrolled in other courses
     """
     course_1 = CourseFactory.create()
     course_2 = CourseFactory.create()
     # make sure self.instructor isn't enrolled in the course
     assert not CourseEnrollment.is_enrolled(self.instructor, self.course.id)
     CourseEnrollment.enroll(self.instructor, course_1.id)
     CourseEnrollment.enroll(self.instructor, course_2.id)
     self.test_send_to_all()
Esempio n. 11
0
 def test_team_counter_get_teams_accessible_by_user(self, username,
                                                    expected_count):
     user = self.users[username]
     try:
         organization_protection_status = teams_api.user_organization_protection_status(
             user, COURSE_KEY1)
     except ValueError:
         self.assertFalse(CourseEnrollment.is_enrolled(user, COURSE_KEY1))
         return
     teams_query_set = teams_api.get_teams_accessible_by_user(
         user, [self.topic_id], COURSE_KEY1, organization_protection_status)
     self.assertEqual(expected_count, teams_query_set.count())
Esempio n. 12
0
 def test_team_counter_add_team_count(self, username, expected_team_count):
     user = self.users[username]
     try:
         organization_protection_status = teams_api.user_organization_protection_status(
             user, COURSE_KEY1)
     except ValueError:
         self.assertFalse(CourseEnrollment.is_enrolled(user, COURSE_KEY1))
         return
     topic = {'id': self.topic_id}
     teams_api.add_team_count(user, [topic], COURSE_KEY1,
                              organization_protection_status)
     self.assertEqual(expected_team_count, topic.get('team_count'))
Esempio n. 13
0
    def has_permission(self, request, view):
        course_key_string = view.kwargs.get('course_id')
        course_key = validate_course_key(course_key_string)

        if GlobalStaff().has_user(request.user):
            return True

        return (
            CourseInstructorRole(course_key).has_user(request.user) or
            CourseStaffRole(course_key).has_user(request.user) or
            CourseEnrollment.is_enrolled(request.user, course_key)
        )
Esempio n. 14
0
 def test_has_specific_team_access_protected_team(self, username,
                                                  expected_return):
     user = self.users[username]
     try:
         self.assertEqual(
             expected_return,
             teams_api.has_specific_team_access(user,
                                                self.team_protected_1))
     except ValueError:
         self.assertFalse(
             CourseEnrollment.is_enrolled(user,
                                          self.team_protected_1.course_id))
Esempio n. 15
0
    def test_existing_active_enrollment(self):
        """ The view should respond with HTTP 409 if the user has an existing active enrollment for the course. """

        # Enroll user in the course
        CourseEnrollment.enroll(self.user, self.course.id)
        assert CourseEnrollment.is_enrolled(self.user, self.course.id)

        response = self._post_to_view()
        assert response.status_code == 409
        msg = Messages.ENROLLMENT_EXISTS.format(username=self.user.username,
                                                course_id=self.course.id)
        self.assertResponseMessage(response, msg)
Esempio n. 16
0
    def add_user(self, user):
        """Adds the given user to the CourseTeam."""
        from lms.djangoapps.teams.api import user_protection_status_matches_team

        if not CourseEnrollment.is_enrolled(user, self.course_id):
            raise NotEnrolledInCourseForTeam
        if CourseTeamMembership.user_in_team_for_teamset(
                user, self.course_id, self.topic_id):
            raise AlreadyOnTeamInTeamset
        if not user_protection_status_matches_team(user, self):
            raise AddToIncompatibleTeamError
        return CourseTeamMembership.objects.create(user=user, team=self)
Esempio n. 17
0
 def test_existing_inactive_enrollment(self):
     """
     If the user has an inactive enrollment for the course, the view should behave as if the
     user has no enrollment.
     """
     # Create an inactive enrollment
     CourseEnrollment.enroll(self.user, self.course.id)
     CourseEnrollment.unenroll(self.user, self.course.id, True)
     self.assertFalse(
         CourseEnrollment.is_enrolled(self.user, self.course.id))
     self.assertIsNotNone(
         get_enrollment(self.user.username, six.text_type(self.course.id)))
Esempio n. 18
0
    def test_enroll_with_email(self, use_json):
        """ Test enrolling using a username as the identifier. """
        response = self.request_bulk_enroll({
            'identifiers': self.notenrolled_student.email,
            'action': 'enroll',
            'email_students': False,
            'courses': self.course_key,
        }, use_json=use_json)
        self.assertEqual(response.status_code, 200)

        # test that the user is now enrolled
        user = User.objects.get(email=self.notenrolled_student.email)
        self.assertTrue(CourseEnrollment.is_enrolled(user, self.course.id))

        # test the response data
        expected = {
            "action": "enroll",
            "auto_enroll": False,
            "email_students": False,
            "courses": {
                self.course_key: {
                    "action": "enroll",
                    "auto_enroll": False,
                    "results": [
                        {
                            "identifier": self.notenrolled_student.email,
                            "before": {
                                "enrollment": False,
                                "auto_enroll": False,
                                "user": True,
                                "allowed": False,
                            },
                            "after": {
                                "enrollment": True,
                                "auto_enroll": False,
                                "user": True,
                                "allowed": False,
                            }
                        }
                    ]
                }
            }
        }

        manual_enrollments = ManualEnrollmentAudit.objects.all()
        self.assertEqual(manual_enrollments.count(), 1)
        self.assertEqual(manual_enrollments[0].state_transition, UNENROLLED_TO_ENROLLED)
        res_json = json.loads(response.content.decode('utf-8'))
        self.assertEqual(res_json, expected)

        # Check the outbox
        self.assertEqual(len(mail.outbox), 0)
Esempio n. 19
0
    def test_user_forum_default_role_on_course_deletion(self):
        """
        Test that a user enrolls and gets "Student" forum role for that course which he creates and remains
        enrolled even the course is deleted and keeps its "Student" forum role for that course
        """
        # check that user has enrollment for this course
        self.assertTrue(
            CourseEnrollment.is_enrolled(self.user, self.course_key))

        # check that user has his default "Student" forum role for this course
        self.assertTrue(
            self.user.roles.filter(name="Student", course_id=self.course_key))

        delete_course(self.course_key, self.user.id)

        # check that user's enrollment for this course is not deleted
        self.assertTrue(
            CourseEnrollment.is_enrolled(self.user, self.course_key))

        # check that user has forum role for this course even after deleting it
        self.assertTrue(
            self.user.roles.filter(name="Student", course_id=self.course_key))
Esempio n. 20
0
    def test_unenroll(self):
        # Enroll the user in the course
        CourseEnrollment.enroll(self.user, self.course.id, mode="honor")

        enrollment = data.update_course_enrollment(self.user.username,
                                                   str(self.course.id),
                                                   is_active=False)

        # Determine that the returned enrollment is inactive.
        assert not enrollment['is_active']

        # Expect that we're no longer enrolled
        assert not CourseEnrollment.is_enrolled(self.user, self.course.id)
Esempio n. 21
0
    def test_user_can_revoke_and_refund(self, mock_course_uuid,
                                        mock_get_course_runs,
                                        mock_refund_entitlement):
        course_entitlement = CourseEntitlementFactory.create(
            user=self.user, mode=CourseMode.VERIFIED)
        mock_get_course_runs.return_value = self.return_values
        mock_course_uuid.return_value = course_entitlement.course_uuid

        url = reverse(self.ENTITLEMENTS_ENROLLMENT_NAMESPACE,
                      args=[str(course_entitlement.uuid)])
        assert course_entitlement.enrollment_course_run is None

        data = {'course_run_id': str(self.course.id)}
        response = self.client.post(
            url,
            data=json.dumps(data),
            content_type='application/json',
        )
        course_entitlement.refresh_from_db()

        assert response.status_code == 201
        assert CourseEnrollment.is_enrolled(self.user, self.course.id)

        # Unenroll with Revoke for refund
        revoke_url = url + '?is_refund=true'
        response = self.client.delete(
            revoke_url,
            content_type='application/json',
        )
        assert response.status_code == 204

        course_entitlement.refresh_from_db()
        assert mock_refund_entitlement.is_called
        assert mock_refund_entitlement.call_args[1][
            'course_entitlement'] == course_entitlement
        assert not CourseEnrollment.is_enrolled(self.user, self.course.id)
        assert course_entitlement.enrollment_course_run is None
        assert course_entitlement.expired_at is not None
Esempio n. 22
0
def check_enrollment(user, course):
    """
    Check if the course requires a learner to be enrolled for access.

    Returns:
        AccessResponse: Either ACCESS_GRANTED or EnrollmentRequiredAccessError.
    """
    if check_public_access(course, [COURSE_VISIBILITY_PUBLIC]):
        return ACCESS_GRANTED

    if CourseEnrollment.is_enrolled(user, course.id):
        return ACCESS_GRANTED

    return EnrollmentRequiredAccessError()
Esempio n. 23
0
    def test_unenrollment_without_filter_configuration(self):
        """
        Test usual unenrollment process without filter's intervention.

        Expected result:
            - CourseUnenrollmentStarted does not have any effect on the unenrollment process.
            - The unenrollment process ends successfully.
        """
        CourseEnrollment.enroll(self.user, self.course.id, mode="audit")

        CourseEnrollment.unenroll(self.user, self.course.id)

        self.assertFalse(
            CourseEnrollment.is_enrolled(self.user, self.course.id))
Esempio n. 24
0
def can_show_certificate_message(course, student, course_grade,
                                 certificates_enabled_for_course):
    """
    Returns True if a course certificate message can be shown
    """
    is_allowlisted = certs_api.is_on_allowlist(student, course.id)
    auto_cert_gen_enabled = auto_certificate_generation_enabled()
    has_active_enrollment = CourseEnrollment.is_enrolled(student, course.id)
    certificates_are_viewable = certs_api.certificates_viewable_for_course(
        course)

    return ((auto_cert_gen_enabled or certificates_enabled_for_course)
            and has_active_enrollment and certificates_are_viewable
            and (course_grade.passed or is_allowlisted))
Esempio n. 25
0
    def test_user_role_on_course_recreate(self):
        """
        Test that creating same course again after deleting it gives user his default
        forum role "Student" for that course
        """
        # check that user has enrollment and his default "Student" forum role for this course
        self.assertTrue(
            CourseEnrollment.is_enrolled(self.user, self.course_key))
        self.assertTrue(
            self.user.roles.filter(name="Student", course_id=self.course_key))

        # delete this course and recreate this course with same user
        delete_course(self.course_key, self.user.id)
        resp = self._create_course_with_given_location(self.course_key)
        self.assertEqual(resp.status_code, 200)

        # check that user has his enrollment for this course
        self.assertTrue(
            CourseEnrollment.is_enrolled(self.user, self.course_key))

        # check that user has his default "Student" forum role for this course
        self.assertTrue(
            self.user.roles.filter(name="Student", course_id=self.course_key))
Esempio n. 26
0
    def test_unenroll_when_unenrollment_disabled(self):
        """
        Tests that a user cannot unenroll when unenrollment has been disabled.
        """
        # Enroll the student in the course
        CourseEnrollment.enroll(self.user, self.course.id, mode="honor")

        # Attempt to unenroll
        resp = self._change_enrollment('unenroll')
        assert resp.status_code == 400

        # Verify that user is still enrolled
        is_enrolled = CourseEnrollment.is_enrolled(self.user, self.course.id)
        assert is_enrolled
 def test_change_to_default_if_verified(self):
     """
     Tests that a student that is a currently enrolled verified student cannot
     accidentally change their enrollment mode
     """
     CourseEnrollment.enroll(self.user, self.course.id, mode='verified')
     assert CourseEnrollment.is_enrolled(self.user, self.course.id)
     # now try to enroll the student in the default mode:
     response = self._enroll_through_view(self.course)
     assert response.status_code == 400
     enrollment_mode, is_active = CourseEnrollment.enrollment_mode_for_user(
         self.user, self.course.id)
     assert is_active
     assert enrollment_mode == 'verified'
Esempio n. 28
0
    def test_start_flow(self):
        # Go to the course mode page, expecting a redirect to the intro step of the
        # payment flow (since this is a professional ed course). Otherwise, the student
        # would have the option to choose their track.
        resp = self.client.get(self.urls['course_modes_choose'])
        self.assertRedirects(
            resp,
            self.urls['verify_student_start_flow'],
            fetch_redirect_response=False,
        )

        # For professional ed courses, expect that the student is NOT enrolled
        # automatically in the course.
        assert not CourseEnrollment.is_enrolled(self.user, self.course_key)
Esempio n. 29
0
def generate_certificate_for_user(request):
    """
    Generate certificates for a user.

    This is meant to be used by support staff through the UI in lms/djangoapps/support

    Arguments:
        request (HttpRequest): The request object

    Returns:
        HttpResponse

    Example Usage:

        POST /certificates/generate
            * username: "******"
            * course_key: "edX/DemoX/Demo_Course"

        Response: 200 OK

    """
    # Check the POST parameters, returning a 400 response if they're not valid.
    params, response = _validate_post_params(request.POST)
    if response is not None:
        return response

    try:
        # Check that the course exists
        CourseOverview.get_from_id(params["course_key"])
    except CourseOverview.DoesNotExist:
        msg = _("The course {course_key} does not exist").format(
            course_key=params["course_key"])
        return HttpResponseBadRequest(msg)
    else:
        # Check that the user is enrolled in the course
        if not CourseEnrollment.is_enrolled(params["user"],
                                            params["course_key"]):
            msg = _(
                "User {username} is not enrolled in the course {course_key}"
            ).format(username=params["user"].username,
                     course_key=params["course_key"])
            return HttpResponseBadRequest(msg)

        # Attempt to generate certificate
        generate_certificates_for_students(
            request,
            params["course_key"],
            student_set="specific_student",
            specific_student_id=params["user"].id)
        return HttpResponse(200)
Esempio n. 30
0
    def get(self, request, *args, **kwargs):
        course_key_string = kwargs.get('course_key_string')
        course_key = CourseKey.from_string(course_key_string)

        if course_home_legacy_is_active(course_key):
            raise Http404

        # Enable NR tracing for this view based on course
        monitoring_utils.set_custom_attribute('course_id', course_key_string)
        monitoring_utils.set_custom_attribute('user_id', request.user.id)
        monitoring_utils.set_custom_attribute('is_staff', request.user.is_staff)

        course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False)
        is_staff = bool(has_access(request.user, 'staff', course_key))

        _, request.user = setup_masquerade(
            request,
            course_key,
            staff_access=is_staff,
            reset_masquerade_data=True,
        )

        # Record user activity for tracking progress towards a user's course goals (for mobile app)
        UserActivity.record_user_activity(request.user, course.id, request=request, only_if_mobile_app=True)

        if not CourseEnrollment.is_enrolled(request.user, course_key) and not is_staff:
            return Response('User not enrolled.', status=401)

        blocks = get_course_date_blocks(course, request.user, request, include_access=True, include_past_dates=True)

        learner_is_full_access = not ContentTypeGatingConfig.enabled_for_enrollment(
            user=request.user,
            course_key=course_key,
        )

        # User locale settings
        user_timezone_locale = user_timezone_locale_prefs(request)
        user_timezone = user_timezone_locale['user_timezone']

        data = {
            'has_ended': course.has_ended(),
            'course_date_blocks': [block for block in blocks if not isinstance(block, TodaysDate)],
            'learner_is_full_access': learner_is_full_access,
            'user_timezone': user_timezone,
        }
        context = self.get_serializer_context()
        context['learner_is_full_access'] = learner_is_full_access
        serializer = self.get_serializer_class()(data, context=context)

        return Response(serializer.data)