Esempio n. 1
0
    def test_exclude_partitions_with_no_groups(self):
        # The cohort partition has no groups defined
        self._set_partitions([
            UserPartition(
                id=0,
                name="Cohort user partition",
                scheme=UserPartition.get_scheme("cohort"),
                description="Cohorted user partition",
                groups=[],
            ),
            UserPartition(
                id=1,
                name="Verification user partition",
                scheme=UserPartition.get_scheme("verification"),
                description="Verification user partition",
                groups=[
                    Group(id=0, name="Group C"),
                ],
            ),
        ])

        # Expect that the partition with no groups is excluded from the results
        partitions = self._get_partition_info()
        self.assertEqual(len(partitions), 1)
        self.assertEqual(partitions[0]["scheme"], "verification")
Esempio n. 2
0
    def setUp(self):
        """Create a dummy course. """
        super(GetUserPartitionInfoTest, self).setUp()
        self.course = CourseFactory()
        self.block = ItemFactory.create(category="problem", parent_location=self.course.location)  # pylint: disable=no-member

        # Set up some default partitions
        self._set_partitions([
            UserPartition(
                id=0,
                name="Cohort user partition",
                scheme=UserPartition.get_scheme("cohort"),
                description="Cohorted user partition",
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name="Random user partition",
                scheme=UserPartition.get_scheme("random"),
                description="Random user partition",
                groups=[
                    Group(id=0, name="Group C"),
                ],
            ),
        ])
    def test_preserves_existing_user_partitions(self):
        # Add other, non-verified partition to the course
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='Cohort user partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohorted user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name='Random user partition',
                scheme=UserPartition.get_scheme('random'),
                description='Random user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
        ]
        self.course = self.store.update_item(self.course, ModuleStoreEnum.UserID.test)

        # Update the verification partitions.
        # The existing partitions should still be available
        self._update_partitions()
        partition_ids = [p.id for p in self.course.user_partitions]
        self.assertEqual(len(partition_ids), 3)
        self.assertIn(0, partition_ids)
        self.assertIn(1, partition_ids)
Esempio n. 4
0
    def test_preserves_existing_user_partitions(self):
        # Add other, non-verified partition to the course
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='Cohort user partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohorted user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name='Random user partition',
                scheme=UserPartition.get_scheme('random'),
                description='Random user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
        ]
        self.course = self.store.update_item(self.course,
                                             ModuleStoreEnum.UserID.test)

        # Update the verification partitions.
        # The existing partitions should still be available
        self._update_partitions()
        partition_ids = [p.id for p in self.course.user_partitions]
        self.assertEqual(len(partition_ids), 3)
        self.assertIn(0, partition_ids)
        self.assertIn(1, partition_ids)
Esempio n. 5
0
    def setUp(self):
        """Create a dummy course. """
        super(GetUserPartitionInfoTest, self).setUp()
        self.course = CourseFactory()
        self.block = ItemFactory.create(category="problem",
                                        parent_location=self.course.location)  # pylint: disable=no-member

        # Set up some default partitions
        self._set_partitions([
            UserPartition(
                id=0,
                name="Cohort user partition",
                scheme=UserPartition.get_scheme("cohort"),
                description="Cohorted user partition",
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name="Random user partition",
                scheme=UserPartition.get_scheme("random"),
                description="Random user partition",
                groups=[
                    Group(id=0, name="Group C"),
                ],
            ),
        ])
Esempio n. 6
0
class PartitionTestCase(TestCase):
    """Base class for test cases that require partitions"""
    TEST_ID = 0
    TEST_NAME = "Mock Partition"
    TEST_DESCRIPTION = "for testing purposes"
    TEST_GROUPS = [Group(0, 'Group 1'), Group(1, 'Group 2')]
    TEST_SCHEME_NAME = "mock"

    def setUp(self):
        super(PartitionTestCase, self).setUp()
        # Set up two user partition schemes: mock and random
        self.non_random_scheme = MockUserPartitionScheme(self.TEST_SCHEME_NAME)
        self.random_scheme = MockUserPartitionScheme("random")
        extensions = [
            Extension(self.non_random_scheme.name,
                      USER_PARTITION_SCHEME_NAMESPACE, self.non_random_scheme,
                      None),
            Extension(self.random_scheme.name, USER_PARTITION_SCHEME_NAMESPACE,
                      self.random_scheme, None),
        ]
        UserPartition.scheme_extensions = ExtensionManager.make_test_instance(
            extensions, namespace=USER_PARTITION_SCHEME_NAMESPACE)

        # Create a test partition
        self.user_partition = UserPartition(self.TEST_ID, self.TEST_NAME,
                                            self.TEST_DESCRIPTION,
                                            self.TEST_GROUPS,
                                            extensions[0].plugin)

        # Make sure the names are set on the schemes (which happens normally in code, but may not happen in tests).
        self.user_partition.get_scheme(self.non_random_scheme.name)
        self.user_partition.get_scheme(self.random_scheme.name)
Esempio n. 7
0
    def test_exclude_inactive_partitions(self):
        # Include an inactive verification scheme
        self._set_partitions([
            UserPartition(
                id=0,
                name="Cohort user partition",
                scheme=UserPartition.get_scheme("cohort"),
                description="Cohorted user partition",
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name="Verification user partition",
                scheme=UserPartition.get_scheme("verification"),
                description="Verification user partition",
                groups=[
                    Group(id=0, name="Group C"),
                ],
                active=False,
            ),
        ])

        # Expect that the inactive scheme is excluded from the results
        partitions = self._get_partition_info()
        self.assertEqual(len(partitions), 1)
        self.assertEqual(partitions[0]["scheme"], "cohort")
Esempio n. 8
0
    def test_exclude_partitions_with_no_groups(self):
        # The cohort partition has no groups defined
        self._set_partitions([
            UserPartition(
                id=0,
                name="Cohort user partition",
                scheme=UserPartition.get_scheme("cohort"),
                description="Cohorted user partition",
                groups=[],
            ),
            UserPartition(
                id=1,
                name="Verification user partition",
                scheme=UserPartition.get_scheme("verification"),
                description="Verification user partition",
                groups=[
                    Group(id=0, name="Group C"),
                ],
            ),
        ])

        # Expect that the partition with no groups is excluded from the results
        partitions = self._get_partition_info()
        self.assertEqual(len(partitions), 1)
        self.assertEqual(partitions[0]["scheme"], "verification")
Esempio n. 9
0
    def test_exclude_inactive_partitions(self):
        # Include an inactive verification scheme
        self._set_partitions([
            UserPartition(
                id=0,
                name="Cohort user partition",
                scheme=UserPartition.get_scheme("cohort"),
                description="Cohorted user partition",
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name="Verification user partition",
                scheme=UserPartition.get_scheme("verification"),
                description="Verification user partition",
                groups=[
                    Group(id=0, name="Group C"),
                ],
                active=False,
            ),
        ])

        # Expect that the inactive scheme is excluded from the results
        partitions = self._get_partition_info()
        self.assertEqual(len(partitions), 1)
        self.assertEqual(partitions[0]["scheme"], "cohort")
Esempio n. 10
0
    def setUp(self):
        super(GroupVisibilityTest, self).setUp()

        chapter = ItemFactory.create(category='chapter',
                                     parent_location=self.course.location)
        sequential = ItemFactory.create(category='sequential',
                                        parent_location=chapter.location)
        vertical = ItemFactory.create(category='vertical',
                                      parent_location=sequential.location)
        html = ItemFactory.create(category='html',
                                  parent_location=vertical.location)
        problem = ItemFactory.create(category='problem',
                                     parent_location=vertical.location,
                                     data="<problem></problem>")
        self.sequential = self.store.get_item(sequential.location)
        self.vertical = self.store.get_item(vertical.location)
        self.html = self.store.get_item(html.location)
        self.problem = self.store.get_item(problem.location)

        # Add partitions to the course
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name="Partition 0",
                description="Partition 0",
                scheme=UserPartition.get_scheme("random"),
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name="Partition 1",
                description="Partition 1",
                scheme=UserPartition.get_scheme("random"),
                groups=[
                    Group(id=0, name="Group C"),
                    Group(id=1, name="Group D"),
                ],
            ),
            UserPartition(
                id=2,
                name="Partition 2",
                description="Partition 2",
                scheme=UserPartition.get_scheme("random"),
                groups=[
                    Group(id=0, name="Group E"),
                    Group(id=1, name="Group F"),
                    Group(id=2, name="Group G"),
                    Group(id=3, name="Group H"),
                ],
            ),
        ]
        self.course = self.store.update_item(self.course,
                                             ModuleStoreEnum.UserID.test)
Esempio n. 11
0
class PartitionTestCase(TestCase):
    """Base class for test cases that require partitions"""
    shard = 2
    TEST_ID = 0
    TEST_NAME = "Mock Partition"
    TEST_DESCRIPTION = "for testing purposes"
    TEST_PARAMETERS = {"location": "block-v1:edX+DemoX+Demo+type@block@uuid"}
    TEST_GROUPS = [Group(0, 'Group 1'), Group(1, 'Group 2')]
    TEST_SCHEME_NAME = "mock"
    ENROLLMENT_TRACK_SCHEME_NAME = "enrollment_track"

    def setUp(self):
        super(PartitionTestCase, self).setUp()
        # Set up two user partition schemes: mock and random
        self.non_random_scheme = MockUserPartitionScheme(self.TEST_SCHEME_NAME)
        self.random_scheme = MockUserPartitionScheme("random")
        self.enrollment_track_scheme = MockEnrollmentTrackUserPartitionScheme(self.ENROLLMENT_TRACK_SCHEME_NAME)
        extensions = [
            Extension(
                self.non_random_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.non_random_scheme, None
            ),
            Extension(
                self.random_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.random_scheme, None
            ),
            Extension(
                self.enrollment_track_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.enrollment_track_scheme, None
            ),
        ]
        UserPartition.scheme_extensions = ExtensionManager.make_test_instance(
            extensions, namespace=USER_PARTITION_SCHEME_NAMESPACE
        )

        # Be sure to clean up the global scheme_extensions after the test.
        self.addCleanup(self.cleanup_scheme_extensions)

        # Create a test partition
        self.user_partition = UserPartition(
            self.TEST_ID,
            self.TEST_NAME,
            self.TEST_DESCRIPTION,
            self.TEST_GROUPS,
            extensions[0].plugin,
            self.TEST_PARAMETERS,
        )

        # Make sure the names are set on the schemes (which happens normally in code, but may not happen in tests).
        self.user_partition.get_scheme(self.non_random_scheme.name)
        self.user_partition.get_scheme(self.random_scheme.name)

    def cleanup_scheme_extensions(self):
        """
        Unset the UserPartition.scheme_extensions cache.
        """
        UserPartition.scheme_extensions = None
Esempio n. 12
0
class PartitionTestCase(TestCase):
    """Base class for test cases that require partitions"""
    shard = 2
    TEST_ID = 0
    TEST_NAME = "Mock Partition"
    TEST_DESCRIPTION = "for testing purposes"
    TEST_PARAMETERS = {"location": "block-v1:edX+DemoX+Demo+type@block@uuid"}
    TEST_GROUPS = [Group(0, 'Group 1'), Group(1, 'Group 2')]
    TEST_SCHEME_NAME = "mock"
    ENROLLMENT_TRACK_SCHEME_NAME = "enrollment_track"

    def setUp(self):
        super(PartitionTestCase, self).setUp()
        # Set up two user partition schemes: mock and random
        self.non_random_scheme = MockUserPartitionScheme(self.TEST_SCHEME_NAME)
        self.random_scheme = MockUserPartitionScheme("random")
        self.enrollment_track_scheme = MockEnrollmentTrackUserPartitionScheme(self.ENROLLMENT_TRACK_SCHEME_NAME)
        extensions = [
            Extension(
                self.non_random_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.non_random_scheme, None
            ),
            Extension(
                self.random_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.random_scheme, None
            ),
            Extension(
                self.enrollment_track_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.enrollment_track_scheme, None
            ),
        ]
        UserPartition.scheme_extensions = ExtensionManager.make_test_instance(
            extensions, namespace=USER_PARTITION_SCHEME_NAMESPACE
        )

        # Be sure to clean up the global scheme_extensions after the test.
        self.addCleanup(self.cleanup_scheme_extensions)

        # Create a test partition
        self.user_partition = UserPartition(
            self.TEST_ID,
            self.TEST_NAME,
            self.TEST_DESCRIPTION,
            self.TEST_GROUPS,
            extensions[0].plugin,
            self.TEST_PARAMETERS,
        )

        # Make sure the names are set on the schemes (which happens normally in code, but may not happen in tests).
        self.user_partition.get_scheme(self.non_random_scheme.name)
        self.user_partition.get_scheme(self.random_scheme.name)

    def cleanup_scheme_extensions(self):
        """
        Unset the UserPartition.scheme_extensions cache.
        """
        UserPartition.scheme_extensions = None
Esempio n. 13
0
    def setUp(self):
        super(GroupVisibilityTest, self).setUp()

        chapter = ItemFactory.create(category='chapter', parent_location=self.course.location)
        sequential = ItemFactory.create(category='sequential', parent_location=chapter.location)
        vertical = ItemFactory.create(category='vertical', parent_location=sequential.location)
        html = ItemFactory.create(category='html', parent_location=vertical.location)
        problem = ItemFactory.create(
            category='problem', parent_location=vertical.location, data="<problem></problem>"
        )
        self.sequential = self.store.get_item(sequential.location)
        self.vertical = self.store.get_item(vertical.location)
        self.html = self.store.get_item(html.location)
        self.problem = self.store.get_item(problem.location)

        # Add partitions to the course
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name="Partition 0",
                description="Partition 0",
                scheme=UserPartition.get_scheme("random"),
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name="Partition 1",
                description="Partition 1",
                scheme=UserPartition.get_scheme("random"),
                groups=[
                    Group(id=0, name="Group C"),
                    Group(id=1, name="Group D"),
                ],
            ),
            UserPartition(
                id=2,
                name="Partition 2",
                description="Partition 2",
                scheme=UserPartition.get_scheme("random"),
                groups=[
                    Group(id=0, name="Group E"),
                    Group(id=1, name="Group F"),
                    Group(id=2, name="Group G"),
                    Group(id=3, name="Group H"),
                ],
            ),
        ]
        self.course = self.store.update_item(self.course, ModuleStoreEnum.UserID.test)
Esempio n. 14
0
    def test_group_access_short_circuits(self):
        """
        Test that the group_access check short-circuits if there are no user_partitions defined
        except user_partitions in use by the split_test module.
        """
        # Initially, "red_cat" user can't view the vertical.
        self.set_group_access(self.chapter,
                              {self.animal_partition.id: [self.dog_group.id]})
        self.check_access(self.red_cat, self.vertical, False)

        # Change the vertical's user_partitions value to the empty list. Now red_cat can view the vertical.
        self.vertical.user_partitions = []
        self.check_access(self.red_cat, self.vertical, True)

        # Change the vertical's user_partitions value to include only "split_test" partitions.
        split_test_partition = UserPartition(
            199,
            'split_test partition',
            'nothing to look at here',
            [Group(2, 'random group')],
            scheme=UserPartition.get_scheme("random"),
        )
        self.vertical.user_partitions = [split_test_partition]
        self.check_access(self.red_cat, self.vertical, True)

        # Finally, add back in a cohort user_partition
        self.vertical.user_partitions = [
            split_test_partition, self.animal_partition
        ]
        self.check_access(self.red_cat, self.vertical, False)
Esempio n. 15
0
    def test_group_access_short_circuits(self):
        """
        Test that the group_access check short-circuits if there are no user_partitions defined
        except user_partitions in use by the split_test module.
        """
        # Initially, "red_cat" user can't view the vertical.
        self.set_group_access(self.chapter_location, {self.animal_partition.id: [self.dog_group.id]})
        self.check_access(self.red_cat, self.vertical_location, False)

        # Change the vertical's user_partitions value to the empty list. Now red_cat can view the vertical.
        self.set_user_partitions(self.vertical_location, [])
        self.check_access(self.red_cat, self.vertical_location, True)

        # Change the vertical's user_partitions value to include only "split_test" partitions.
        split_test_partition = UserPartition(
            199,
            'split_test partition',
            'nothing to look at here',
            [Group(2, 'random group')],
            scheme=UserPartition.get_scheme("random"),
        )
        self.set_user_partitions(self.vertical_location, [split_test_partition])
        self.check_access(self.red_cat, self.vertical_location, True)

        # Finally, add back in a cohort user_partition
        self.set_user_partitions(self.vertical_location, [split_test_partition, self.animal_partition])
        self.check_access(self.red_cat, self.vertical_location, False)
Esempio n. 16
0
    def setUp(self):
        super(ReverificationPartitionTest, self).setUp()

        # creating course, checkpoint location and user partition mock object.
        self.course = CourseFactory.create()
        self.checkpoint_location = u'i4x://{org}/{course}/edx-reverification-block/first_uuid'.format(
            org=self.course.id.org, course=self.course.id.course
        )

        scheme = UserPartition.get_scheme("verification")
        self.user_partition = UserPartition(
            id=0,
            name=u"Verification Checkpoint",
            description=u"Verification Checkpoint",
            scheme=scheme,
            parameters={"location": self.checkpoint_location},
            groups=[
                Group(scheme.ALLOW, "Allow access to content"),
                Group(scheme.DENY, "Deny access to content"),
            ]
        )

        self.first_checkpoint = VerificationCheckpoint.objects.create(
            course_id=self.course.id,
            checkpoint_location=self.checkpoint_location
        )
Esempio n. 17
0
def _create_enrollment_track_partition(course):
    """
    Create and return the dynamic enrollment track user partition.
    If it cannot be created, None is returned.
    """
    if not FEATURES.get('ENABLE_ENROLLMENT_TRACK_USER_PARTITION'):
        return None

    try:
        enrollment_track_scheme = UserPartition.get_scheme("enrollment_track")
    except UserPartitionError:
        log.warning("No 'enrollment_track' scheme registered, EnrollmentTrackUserPartition will not be created.")
        return None

    used_ids = set(p.id for p in course.user_partitions)
    if ENROLLMENT_TRACK_PARTITION_ID in used_ids:
        log.warning(
            "Can't add 'enrollment_track' partition, as ID {id} is assigned to {partition} in course {course}.".format(
                id=ENROLLMENT_TRACK_PARTITION_ID,
                partition=_get_partition_from_id(course.user_partitions, ENROLLMENT_TRACK_PARTITION_ID).name,
                course=unicode(course.id)
            )
        )
        return None

    partition = enrollment_track_scheme.create_user_partition(
        id=ENROLLMENT_TRACK_PARTITION_ID,
        name=_(u"Enrollment Track Groups"),
        description=_(u"Partition for segmenting users by enrollment track"),
        parameters={"course_id": unicode(course.id)}
    )
    return partition
Esempio n. 18
0
def _create_enrollment_track_partition(course):
    """
    Create and return the dynamic enrollment track user partition.
    If it cannot be created, None is returned.
    """
    if not FEATURES.get('ENABLE_ENROLLMENT_TRACK_USER_PARTITION'):
        return None

    try:
        enrollment_track_scheme = UserPartition.get_scheme("enrollment_track")
    except UserPartitionError:
        log.warning(
            "No 'enrollment_track' scheme registered, EnrollmentTrackUserPartition will not be created."
        )
        return None

    used_ids = set(p.id for p in course.user_partitions)
    if ENROLLMENT_TRACK_PARTITION_ID in used_ids:
        log.warning(
            "Can't add 'enrollment_track' partition, as ID {id} is assigned to {partition} in course {course}."
            .format(id=ENROLLMENT_TRACK_PARTITION_ID,
                    partition=_get_partition_from_id(
                        course.user_partitions,
                        ENROLLMENT_TRACK_PARTITION_ID).name,
                    course=unicode(course.id)))
        return None

    partition = enrollment_track_scheme.create_user_partition(
        id=ENROLLMENT_TRACK_PARTITION_ID,
        name=_(u"Enrollment Track Groups"),
        description=_(u"Partition for segmenting users by enrollment track"),
        parameters={"course_id": unicode(course.id)})
    return partition
Esempio n. 19
0
def create_content_gating_partition(course):
    """
    Create and return the Content Gating user partition.
    """

    if not (CONTENT_TYPE_GATING_FLAG.is_enabled() or CONTENT_TYPE_GATING_STUDIO_UI_FLAG.is_enabled()):
        return None

    try:
        content_gate_scheme = UserPartition.get_scheme("content_type_gate")
    except UserPartitionError:
        LOG.warning("No 'content_type_gate' scheme registered, ContentTypeGatingPartitionScheme will not be created.")
        return None

    used_ids = set(p.id for p in course.user_partitions)
    if CONTENT_GATING_PARTITION_ID in used_ids:
        # It's possible for course authors to add arbitrary partitions via XML import. If they do, and create a
        # partition with id 51, it will collide with the Content Gating Partition. We'll catch that here, and
        # then fix the course content as needed (or get the course team to).
        LOG.warning(
            "Can't add 'content_type_gate' partition, as ID {id} is assigned to {partition} in course {course}.".format(
                id=CONTENT_GATING_PARTITION_ID,
                partition=_get_partition_from_id(course.user_partitions, CONTENT_GATING_PARTITION_ID).name,
                course=unicode(course.id)
            )
        )
        return None

    partition = content_gate_scheme.create_user_partition(
        id=CONTENT_GATING_PARTITION_ID,
        name=_(u"Feature-based Enrollments"),
        description=_(u"Partition for segmenting users by access to gated content types"),
        parameters={"course_id": unicode(course.id)}
    )
    return partition
Esempio n. 20
0
    def test_can_get_correct_usage_info_for_split_test(self):
        """
        When a split test is created and content group access is set for a problem within a group,
        the usage info should return a url to the split test, not to the group.
        """
        # Create user partition for groups in the split test,
        # and another partition to set group access for the problem within the split test.
        self._add_user_partitions(count=1)
        self.course.user_partitions += [
            UserPartition(
                id=1,
                name='Cohort User Partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohort User Partition',
                groups=[Group(id=3, name="Problem Group")],
            ),
        ]
        self.store.update_item(self.course, ModuleStoreEnum.UserID.test)

        __, split_test, problem = self._create_content_experiment(
            cid=0, name_suffix='0', group_id=3, cid_for_problem=1)

        expected = {
            'id':
            1,
            'name':
            'Cohort User Partition',
            'scheme':
            'cohort',
            'description':
            'Cohort User Partition',
            'version':
            UserPartition.VERSION,
            'groups': [
                {
                    'id':
                    3,
                    'name':
                    'Problem Group',
                    'version':
                    1,
                    'usage': [{
                        'url':
                        '/container/{}'.format(split_test.location),
                        'label':
                        'Condition 1 vertical / Test Problem'
                    }]
                },
            ],
            u'parameters': {},
            u'active':
            True,
        }
        actual = self._get_user_partition('cohort')

        self.assertEqual(actual, expected)
    def test_create_user_partition(self):
        user_partition = UserPartition.get_scheme('enrollment_track').create_user_partition(
            301, "partition", "test partition", parameters={"course_id": unicode(self.course.id)}
        )
        self.assertEqual(type(user_partition), EnrollmentTrackUserPartition)
        self.assertEqual(user_partition.name, "partition")

        groups = user_partition.groups
        self.assertEqual(1, len(groups))
        self.assertEqual("Audit", groups[0].name)
    def test_create_user_partition(self):
        user_partition = UserPartition.get_scheme('enrollment_track').create_user_partition(
            301, "partition", "test partition", parameters={"course_id": str(self.course.id)}
        )
        assert isinstance(user_partition, EnrollmentTrackUserPartition)
        assert user_partition.name == 'partition'

        groups = user_partition.groups
        assert 1 == len(groups)
        assert 'Audit' == groups[0].name
Esempio n. 23
0
    def test_can_handle_multiple_partitions(self):
        # Create the user partitions
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='Cohort user partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohorted user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name='Random user partition',
                scheme=UserPartition.get_scheme('random'),
                description='Random user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
        ]
        self.store.update_item(self.course, ModuleStoreEnum.UserID.test)

        # Assign group access rules for multiple partitions, one of which is a cohorted partition
        __, problem = self._create_problem_with_content_group(0, 1)
        problem.group_access = {
            0: [0],
            1: [1],
        }
        self.store.update_item(problem, ModuleStoreEnum.UserID.test)

        # This used to cause an exception since the code assumed that
        # only one partition would be available.
        actual = GroupConfiguration.get_content_groups_usage_info(
            self.store, self.course)
        self.assertEqual(actual.keys(), [0])

        actual = GroupConfiguration.get_content_groups_items_usage_info(
            self.store, self.course)
        self.assertEqual(actual.keys(), [0])
Esempio n. 24
0
def create_enrollment_track_partition(course):
    """
    Create an EnrollmentTrackUserPartition instance for the given course.
    """
    enrollment_track_scheme = UserPartition.get_scheme("enrollment_track")
    partition = enrollment_track_scheme.create_user_partition(
        id=1,
        name="Test Enrollment Track Partition",
        description="Test partition for segmenting users by enrollment track",
        parameters={"course_id": unicode(course.id)})
    return partition
Esempio n. 25
0
    def test_can_handle_duplicate_group_ids(self):
        # Create the user partitions
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='Cohort user partition 1',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohorted user partition',
                groups=[
                    Group(id=2, name="Group 1A"),
                    Group(id=3, name="Group 1B"),
                ],
            ),
            UserPartition(
                id=1,
                name='Cohort user partition 2',
                scheme=UserPartition.get_scheme('cohort'),
                description='Random user partition',
                groups=[
                    Group(id=2, name="Group 2A"),
                    Group(id=3, name="Group 2B"),
                ],
            ),
        ]
        self.store.update_item(self.course, ModuleStoreEnum.UserID.test)

        # Assign group access rules for multiple partitions, one of which is a cohorted partition
        self._create_problem_with_content_group(0, 2, name_suffix='0')
        self._create_problem_with_content_group(1, 3, name_suffix='1')

        # This used to cause an exception since the code assumed that
        # only one partition would be available.
        actual = GroupConfiguration.get_partitions_usage_info(self.store, self.course)
        self.assertEqual(list(actual.keys()), [0, 1])
        self.assertEqual(list(actual[0].keys()), [2])
        self.assertEqual(list(actual[1].keys()), [3])

        actual = GroupConfiguration.get_content_groups_items_usage_info(self.store, self.course)
        self.assertEqual(list(actual.keys()), [0, 1])
        self.assertEqual(list(actual[0].keys()), [2])
        self.assertEqual(list(actual[1].keys()), [3])
    def test_can_handle_duplicate_group_ids(self):
        # Create the user partitions
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='Cohort user partition 1',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohorted user partition',
                groups=[
                    Group(id=2, name="Group 1A"),
                    Group(id=3, name="Group 1B"),
                ],
            ),
            UserPartition(
                id=1,
                name='Cohort user partition 2',
                scheme=UserPartition.get_scheme('cohort'),
                description='Random user partition',
                groups=[
                    Group(id=2, name="Group 2A"),
                    Group(id=3, name="Group 2B"),
                ],
            ),
        ]
        self.store.update_item(self.course, ModuleStoreEnum.UserID.test)

        # Assign group access rules for multiple partitions, one of which is a cohorted partition
        self._create_problem_with_content_group(0, 2, name_suffix='0')
        self._create_problem_with_content_group(1, 3, name_suffix='1')

        # This used to cause an exception since the code assumed that
        # only one partition would be available.
        actual = GroupConfiguration.get_partitions_usage_info(self.store, self.course)
        self.assertEqual(actual.keys(), [0, 1])
        self.assertEqual(actual[0].keys(), [2])
        self.assertEqual(actual[1].keys(), [3])

        actual = GroupConfiguration.get_content_groups_items_usage_info(self.store, self.course)
        self.assertEqual(actual.keys(), [0, 1])
        self.assertEqual(actual[0].keys(), [2])
        self.assertEqual(actual[1].keys(), [3])
    def test_can_handle_multiple_partitions(self):
        # Create the user partitions
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='Cohort user partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohorted user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
            UserPartition(
                id=1,
                name='Random user partition',
                scheme=UserPartition.get_scheme('random'),
                description='Random user partition',
                groups=[
                    Group(id=0, name="Group A"),
                    Group(id=1, name="Group B"),
                ],
            ),
        ]
        self.store.update_item(self.course, ModuleStoreEnum.UserID.test)

        # Assign group access rules for multiple partitions, one of which is a cohorted partition
        __, problem = self._create_problem_with_content_group(0, 1)
        problem.group_access = {
            0: [0],
            1: [1],
        }
        self.store.update_item(problem, ModuleStoreEnum.UserID.test)

        # This used to cause an exception since the code assumed that
        # only one partition would be available.
        actual = GroupConfiguration.get_content_groups_usage_info(self.store, self.course)
        self.assertEqual(actual.keys(), [0])

        actual = GroupConfiguration.get_content_groups_items_usage_info(self.store, self.course)
        self.assertEqual(actual.keys(), [0])
    def test_can_get_correct_usage_info_for_unit(self):
        """
        When group access is set on the unit level, the usage info should return a url to the unit, not
        the sequential parent of the unit.
        """
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='User Partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='User Partition',
                groups=[
                    Group(id=0, name="Group")
                ],
            ),
        ]
        vertical, __ = self._create_problem_with_content_group(
            cid=0, group_id=0, name_suffix='0'
        )

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", vertical.location),
            data={'metadata': {'group_access': {0: [0]}}}
        )

        actual = self._get_user_partition('cohort')
        # order of usage list is arbitrary, sort for reliable comparison
        actual['groups'][0]['usage'].sort(key=itemgetter('label'))
        expected = {
            'id': 0,
            'name': 'User Partition',
            'scheme': 'cohort',
            'description': 'User Partition',
            'version': UserPartition.VERSION,
            'groups': [
                {'id': 0, 'name': 'Group', 'version': 1, 'usage': [
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Subsection 0 / Test Unit 0"
                    },
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Unit 0 / Test Problem 0"
                    }
                ]},
            ],
            u'parameters': {},
            u'active': True,
        }

        self.maxDiff = None

        assert actual == expected
def create_enrollment_track_partition(course):
    """
    Create an EnrollmentTrackUserPartition instance for the given course.
    """
    enrollment_track_scheme = UserPartition.get_scheme("enrollment_track")
    partition = enrollment_track_scheme.create_user_partition(
        id=1,
        name="Test Enrollment Track Partition",
        description="Test partition for segmenting users by enrollment track",
        parameters={"course_id": unicode(course.id)}
    )
    return partition
Esempio n. 30
0
    def test_can_get_correct_usage_info_for_unit(self):
        """
        When group access is set on the unit level, the usage info should return a url to the unit, not
        the sequential parent of the unit.
        """
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='User Partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='User Partition',
                groups=[
                    Group(id=0, name="Group")
                ],
            ),
        ]
        vertical, __ = self._create_problem_with_content_group(
            cid=0, group_id=0, name_suffix='0'
        )

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", vertical.location),
            data={'metadata': {'group_access': {0: [0]}}}
        )

        actual = self._get_user_partition('cohort')
        # order of usage list is arbitrary, sort for reliable comparison
        actual['groups'][0]['usage'].sort(key=itemgetter('label'))
        expected = {
            'id': 0,
            'name': 'User Partition',
            'scheme': 'cohort',
            'description': 'User Partition',
            'version': UserPartition.VERSION,
            'groups': [
                {'id': 0, 'name': 'Group', 'version': 1, 'usage': [
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Subsection 0 / Test Unit 0"
                    },
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Unit 0 / Test Problem 0"
                    }
                ]},
            ],
            u'parameters': {},
            u'active': True,
        }

        self.maxDiff = None

        assert actual == expected
Esempio n. 31
0
class PartitionTestCase(TestCase):
    """Base class for test cases that require partitions"""
    TEST_ID = 0
    TEST_NAME = "Mock Partition"
    TEST_DESCRIPTION = "for testing purposes"
    TEST_GROUPS = [Group(0, 'Group 1'), Group(1, 'Group 2')]
    TEST_SCHEME_NAME = "mock"

    def setUp(self):
        super(PartitionTestCase, self).setUp()
        # Set up two user partition schemes: mock and random
        self.non_random_scheme = MockUserPartitionScheme(self.TEST_SCHEME_NAME)
        self.random_scheme = MockUserPartitionScheme("random")
        extensions = [
            Extension(
                self.non_random_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.non_random_scheme, None
            ),
            Extension(
                self.random_scheme.name, USER_PARTITION_SCHEME_NAMESPACE, self.random_scheme, None
            ),
        ]
        UserPartition.scheme_extensions = ExtensionManager.make_test_instance(
            extensions, namespace=USER_PARTITION_SCHEME_NAMESPACE
        )

        # Create a test partition
        self.user_partition = UserPartition(
            self.TEST_ID,
            self.TEST_NAME,
            self.TEST_DESCRIPTION,
            self.TEST_GROUPS,
            extensions[0].plugin
        )

        # Make sure the names are set on the schemes (which happens normally in code, but may not happen in tests).
        self.user_partition.get_scheme(self.non_random_scheme.name)
        self.user_partition.get_scheme(self.random_scheme.name)
Esempio n. 32
0
def create_content_gating_partition(course):
    """
    Create and return the Content Gating user partition.
    """

    enabled_for_course = ContentTypeGatingConfig.enabled_for_course(
        course_key=course.id)
    studio_override_for_course = ContentTypeGatingConfig.current(
        course_key=course.id).studio_override_enabled
    if not (enabled_for_course or studio_override_for_course):
        return None

    try:
        content_gate_scheme = UserPartition.get_scheme(
            CONTENT_TYPE_GATING_SCHEME)
    except UserPartitionError:
        LOG.warning(
            u"No %r scheme registered, ContentTypeGatingPartitionScheme will not be created.",
            CONTENT_TYPE_GATING_SCHEME)
        return None

    used_ids = set(p.id for p in course.user_partitions)
    if CONTENT_GATING_PARTITION_ID in used_ids:
        # It's possible for course authors to add arbitrary partitions via XML import. If they do, and create a
        # partition with id 51, it will collide with the Content Gating Partition. We'll catch that here, and
        # then fix the course content as needed (or get the course team to).
        LOG.warning(
            u"Can't add %r partition, as ID %r is assigned to %r in course %s.",
            CONTENT_TYPE_GATING_SCHEME,
            CONTENT_GATING_PARTITION_ID,
            _get_partition_from_id(course.user_partitions,
                                   CONTENT_GATING_PARTITION_ID).name,
            six.text_type(course.id),
        )
        return None

    partition = content_gate_scheme.create_user_partition(
        id=CONTENT_GATING_PARTITION_ID,
        # Content gating partition name should not be marked for translations
        # edX mobile apps expect it in english
        name=u"Feature-based Enrollments",
        description=_(
            u"Partition for segmenting users by access to gated content types"
        ),
        parameters={"course_id": six.text_type(course.id)})
    return partition
    def test_can_get_correct_usage_info_for_split_test(self):
        """
        When a split test is created and content group access is set for a problem within a group,
        the usage info should return a url to the split test, not to the group.
        """
        # Create user partition for groups in the split test,
        # and another partition to set group access for the problem within the split test.
        self._add_user_partitions(count=1)
        self.course.user_partitions += [
            UserPartition(
                id=1,
                name='Cohort User Partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='Cohort User Partition',
                groups=[
                    Group(id=3, name="Problem Group")
                ],
            ),
        ]
        self.store.update_item(self.course, ModuleStoreEnum.UserID.test)

        __, split_test, problem = self._create_content_experiment(cid=0, name_suffix='0', group_id=3, cid_for_problem=1)

        expected = {
            'id': 1,
            'name': 'Cohort User Partition',
            'scheme': 'cohort',
            'description': 'Cohort User Partition',
            'version': UserPartition.VERSION,
            'groups': [
                {'id': 3, 'name': 'Problem Group', 'version': 1, 'usage': [
                    {
                        'url': '/container/{}'.format(split_test.location),
                        'label': 'Condition 1 vertical / Test Problem'
                    }
                ]},
            ],
            u'parameters': {},
            u'active': True,
        }
        actual = self._get_user_partition('cohort')

        self.assertEqual(actual, expected)
 def create_verification_user_partitions(self, checkpoint_names):
     """
     Create user partitions for verification checkpoints.
     """
     scheme = UserPartition.get_scheme("verification")
     self.course.user_partitions = [
         UserPartition(
             id=0,
             name=checkpoint_name,
             description="Verification checkpoint",
             scheme=scheme,
             groups=[
                 Group(scheme.ALLOW, "Completed verification at {}".format(checkpoint_name)),
                 Group(scheme.DENY, "Did not complete verification at {}".format(checkpoint_name)),
             ],
         )
         for checkpoint_name in checkpoint_names
     ]
     self.store.update_item(self.course, self.user.id)
Esempio n. 35
0
def create_enrollment_track_partition_with_course_id(course_id):
    """
    Create and return the dynamic enrollment track user partition based only on course_id.
    If it cannot be created, None is returned.
    """
    if not FEATURES.get('ENABLE_ENROLLMENT_TRACK_USER_PARTITION'):
        return None

    try:
        enrollment_track_scheme = UserPartition.get_scheme("enrollment_track")
    except UserPartitionError:
        log.warning("No 'enrollment_track' scheme registered, EnrollmentTrackUserPartition will not be created.")
        return None

    partition = enrollment_track_scheme.create_user_partition(
        id=ENROLLMENT_TRACK_PARTITION_ID,
        name=_("Enrollment Track Groups"),
        description=_("Partition for segmenting users by enrollment track"),
        parameters={"course_id": str(course_id)}
    )
    return partition
Esempio n. 36
0
def create_content_gating_partition(course):
    """
    Create and return the Content Gating user partition.
    """

    enabled_for_course = ContentTypeGatingConfig.enabled_for_course(course_key=course.id)
    studio_override_for_course = ContentTypeGatingConfig.current(course_key=course.id).studio_override_enabled
    if not (enabled_for_course or studio_override_for_course):
        return None

    try:
        content_gate_scheme = UserPartition.get_scheme(CONTENT_TYPE_GATING_SCHEME)
    except UserPartitionError:
        LOG.warning(
            u"No %r scheme registered, ContentTypeGatingPartitionScheme will not be created.",
            CONTENT_TYPE_GATING_SCHEME
        )
        return None

    used_ids = set(p.id for p in course.user_partitions)
    if CONTENT_GATING_PARTITION_ID in used_ids:
        # It's possible for course authors to add arbitrary partitions via XML import. If they do, and create a
        # partition with id 51, it will collide with the Content Gating Partition. We'll catch that here, and
        # then fix the course content as needed (or get the course team to).
        LOG.warning(
            u"Can't add %r partition, as ID %r is assigned to %r in course %s.",
            CONTENT_TYPE_GATING_SCHEME,
            CONTENT_GATING_PARTITION_ID,
            _get_partition_from_id(course.user_partitions, CONTENT_GATING_PARTITION_ID).name,
            unicode(course.id),
        )
        return None

    partition = content_gate_scheme.create_user_partition(
        id=CONTENT_GATING_PARTITION_ID,
        name=_(u"Feature-based Enrollments"),
        description=_(u"Partition for segmenting users by access to gated content types"),
        parameters={"course_id": unicode(course.id)}
    )
    return partition
 def create_verification_user_partitions(self, checkpoint_names):
     """
     Create user partitions for verification checkpoints.
     """
     scheme = UserPartition.get_scheme("verification")
     self.course.user_partitions = [
         UserPartition(
             id=0,
             name=checkpoint_name,
             description="Verification checkpoint",
             scheme=scheme,
             groups=[
                 Group(
                     scheme.ALLOW, "Completed verification at {}".format(
                         checkpoint_name)),
                 Group(
                     scheme.DENY,
                     "Did not complete verification at {}".format(
                         checkpoint_name)),
             ],
         ) for checkpoint_name in checkpoint_names
     ]
     self.store.update_item(self.course, self.user.id)
Esempio n. 38
0
 def test_singular_deleted_group(self):
     """
     Verify that a partition with only one deleted group is
     shown in the partition info with the group marked as deleted
     """
     self._set_partitions([
         UserPartition(
             id=0,
             name="Cohort user partition",
             scheme=UserPartition.get_scheme("cohort"),
             description="Cohorted user partition",
             groups=[],
         ),
     ])
     self._set_group_access({0: [1]})
     partitions = self._get_partition_info()
     groups = partitions[0]["groups"]
     self.assertEqual(len(groups), 1)
     self.assertEqual(groups[0], {
         "id": 1,
         "name": "Deleted Group",
         "selected": True,
         "deleted": True,
     })
Esempio n. 39
0
 def test_singular_deleted_group(self):
     """
     Verify that a partition with only one deleted group is
     shown in the partition info with the group marked as deleted
     """
     self._set_partitions([
         UserPartition(
             id=0,
             name="Cohort user partition",
             scheme=UserPartition.get_scheme("cohort"),
             description="Cohorted user partition",
             groups=[],
         ),
     ])
     self._set_group_access({0: [1]})
     partitions = self._get_partition_info()
     groups = partitions[0]["groups"]
     self.assertEqual(len(groups), 1)
     self.assertEqual(groups[0], {
         "id": 1,
         "name": "Deleted Group",
         "selected": True,
         "deleted": True,
     })
Esempio n. 40
0
 def test_get_scheme(self):
     self.assertEqual(UserPartition.get_scheme('cohort'),
                      CohortPartitionScheme)
     with self.assertRaisesRegexp(UserPartitionError,
                                  'Unrecognized scheme'):
         UserPartition.get_scheme('other')
Esempio n. 41
0
def _set_verification_partitions(course_key, icrv_blocks):
    """
    Create or update user partitions in the course.

    Ensures that each ICRV block in the course has an associated user partition
    with the groups ALLOW and DENY.

    Arguments:
        course_key (CourseKey): Identifier for the course.
        icrv_blocks (list of XBlock): In-course reverification blocks, e.g. reverification checkpoints.

    Returns:
        list of UserPartition
    """
    scheme = UserPartition.get_scheme(VERIFICATION_SCHEME_NAME)
    if scheme is None:
        log.error("Could not retrieve user partition scheme with ID %s",
                  VERIFICATION_SCHEME_NAME)
        return []

    course = modulestore().get_course(course_key)
    if course is None:
        log.error("Could not find course %s", course_key)
        return []

    verified_partitions = course.get_user_partitions_for_scheme(scheme)
    partition_id_for_location = {
        p.parameters["location"]: p.id
        for p in verified_partitions if "location" in p.parameters
    }

    partitions = []
    for block in icrv_blocks:
        partition = UserPartition(
            id=partition_id_for_location.get(unicode(block.location),
                                             _unique_partition_id(course)),
            name=block.related_assessment,
            description=u"Verification checkpoint at {}".format(
                block.related_assessment),
            scheme=scheme,
            parameters={"location": unicode(block.location)},
            groups=[
                Group(
                    scheme.ALLOW, "Completed verification at {}".format(
                        block.related_assessment)),
                Group(
                    scheme.DENY, "Did not complete verification at {}".format(
                        block.related_assessment)),
            ])
        partitions.append(partition)

        log.info((
            "Configured partition %s for course %s using a verified partition scheme "
            "for the in-course-reverification checkpoint at location %s"),
                 partition.id, course_key, partition.parameters["location"])

    # Preserve existing, non-verified partitions from the course
    # Mark partitions for deleted in-course reverification as disabled.
    partitions += _other_partitions(verified_partitions, partitions,
                                    course_key)
    course.set_user_partitions_for_scheme(partitions, scheme)
    modulestore().update_item(course, ModuleStoreEnum.UserID.system)

    log.info("Saved updated partitions for the course %s", course_key)

    return partitions
 def test_get_scheme(self):
     self.assertEqual(UserPartition.get_scheme('random'),
                      RandomUserPartitionScheme)
     with self.assertRaisesRegex(UserPartitionError, 'Unrecognized scheme'):
         UserPartition.get_scheme('other')
Esempio n. 43
0
    def setUp(self):
        super(GroupAccessTestCase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments

        UserPartition.scheme_extensions = ExtensionManager.make_test_instance(
            [
                Extension("memory", USER_PARTITION_SCHEME_NAMESPACE,
                          MemoryUserPartitionScheme(), None),
                Extension("random", USER_PARTITION_SCHEME_NAMESPACE,
                          MemoryUserPartitionScheme(), None)
            ],
            namespace=USER_PARTITION_SCHEME_NAMESPACE)

        self.cat_group = Group(10, 'cats')
        self.dog_group = Group(20, 'dogs')
        self.worm_group = Group(30, 'worms')
        self.animal_partition = UserPartition(
            0,
            'Pet Partition',
            'which animal are you?',
            [self.cat_group, self.dog_group, self.worm_group],
            scheme=UserPartition.get_scheme("memory"),
        )

        self.red_group = Group(1000, 'red')
        self.blue_group = Group(2000, 'blue')
        self.gray_group = Group(3000, 'gray')
        self.color_partition = UserPartition(
            100,
            'Color Partition',
            'what color are you?',
            [self.red_group, self.blue_group, self.gray_group],
            scheme=UserPartition.get_scheme("memory"),
        )

        self.course = CourseFactory.create(
            user_partitions=[self.animal_partition, self.color_partition], )
        with self.store.bulk_operations(self.course.id, emit_signals=False):
            chapter = ItemFactory.create(category='chapter',
                                         parent=self.course)
            section = ItemFactory.create(category='sequential', parent=chapter)
            vertical = ItemFactory.create(category='vertical', parent=section)
            component = ItemFactory.create(category='problem', parent=vertical)

            self.chapter_location = chapter.location
            self.section_location = section.location
            self.vertical_location = vertical.location
            self.component_location = component.location

        self.red_cat = UserFactory()  # student in red and cat groups
        self.set_user_group(self.red_cat, self.animal_partition,
                            self.cat_group)
        self.set_user_group(self.red_cat, self.color_partition, self.red_group)

        self.blue_dog = UserFactory()  # student in blue and dog groups
        self.set_user_group(self.blue_dog, self.animal_partition,
                            self.dog_group)
        self.set_user_group(self.blue_dog, self.color_partition,
                            self.blue_group)

        self.white_mouse = UserFactory()  # student in no group

        self.gray_worm = UserFactory()  # student in deleted group
        self.set_user_group(self.gray_worm, self.animal_partition,
                            self.worm_group)
        self.set_user_group(self.gray_worm, self.color_partition,
                            self.gray_group)
        # delete the gray/worm groups from the partitions now so we can test scenarios
        # for user whose group is missing.
        self.animal_partition.groups.pop()
        self.color_partition.groups.pop()

        # add a staff user, whose access will be unconditional in spite of group access.
        self.staff = StaffFactory.create(course_key=self.course.id)
 def test_get_scheme(self):
     self.assertEqual(UserPartition.get_scheme("cohort"), CohortPartitionScheme)
     with self.assertRaisesRegexp(UserPartitionError, "Unrecognized scheme"):
         UserPartition.get_scheme("other")
Esempio n. 45
0
 def test_get_scheme(self):
     """
     Ensure that the scheme extension is correctly plugged in (via entry point in setup.py)
     """
     self.assertEquals(UserPartition.get_scheme('enrollment_track'),
                       EnrollmentTrackPartitionScheme)
 def test_get_scheme(self):
     self.assertEqual(UserPartition.get_scheme('random'), RandomUserPartitionScheme)
     with self.assertRaisesRegexp(UserPartitionError, 'Unrecognized scheme'):
         UserPartition.get_scheme('other')
 def test_get_scheme(self):
     assert UserPartition.get_scheme('cohort') == CohortPartitionScheme
     with self.assertRaisesRegex(UserPartitionError, 'Unrecognized scheme'):
         UserPartition.get_scheme('other')
 def test_get_scheme(self):
     """
     Ensure that the scheme extension is correctly plugged in (via entry point in setup.py)
     """
     self.assertEquals(UserPartition.get_scheme('enrollment_track'), EnrollmentTrackPartitionScheme)
Esempio n. 49
0
    def setUp(self):
        super(GroupAccessTestCase, self).setUp()

        UserPartition.scheme_extensions = ExtensionManager.make_test_instance(
            [
                Extension(
                    "memory",
                    USER_PARTITION_SCHEME_NAMESPACE,
                    MemoryUserPartitionScheme(),
                    None
                ),
                Extension(
                    "random",
                    USER_PARTITION_SCHEME_NAMESPACE,
                    MemoryUserPartitionScheme(),
                    None
                )
            ],
            namespace=USER_PARTITION_SCHEME_NAMESPACE
        )

        self.cat_group = Group(10, 'cats')
        self.dog_group = Group(20, 'dogs')
        self.worm_group = Group(30, 'worms')
        self.animal_partition = UserPartition(
            0,
            'Pet Partition',
            'which animal are you?',
            [self.cat_group, self.dog_group, self.worm_group],
            scheme=UserPartition.get_scheme("memory"),
        )

        self.red_group = Group(1000, 'red')
        self.blue_group = Group(2000, 'blue')
        self.gray_group = Group(3000, 'gray')
        self.color_partition = UserPartition(
            100,
            'Color Partition',
            'what color are you?',
            [self.red_group, self.blue_group, self.gray_group],
            scheme=UserPartition.get_scheme("memory"),
        )

        self.course = CourseFactory.create(
            user_partitions=[self.animal_partition, self.color_partition],
        )
        with self.store.bulk_operations(self.course.id, emit_signals=False):
            chapter = ItemFactory.create(category='chapter', parent=self.course)
            section = ItemFactory.create(category='sequential', parent=chapter)
            vertical = ItemFactory.create(category='vertical', parent=section)
            component = ItemFactory.create(category='problem', parent=vertical)

            self.chapter_location = chapter.location
            self.section_location = section.location
            self.vertical_location = vertical.location
            self.component_location = component.location

        self.red_cat = UserFactory()  # student in red and cat groups
        self.set_user_group(self.red_cat, self.animal_partition, self.cat_group)
        self.set_user_group(self.red_cat, self.color_partition, self.red_group)

        self.blue_dog = UserFactory()  # student in blue and dog groups
        self.set_user_group(self.blue_dog, self.animal_partition, self.dog_group)
        self.set_user_group(self.blue_dog, self.color_partition, self.blue_group)

        self.white_mouse = UserFactory()  # student in no group

        self.gray_worm = UserFactory()  # student in deleted group
        self.set_user_group(self.gray_worm, self.animal_partition, self.worm_group)
        self.set_user_group(self.gray_worm, self.color_partition, self.gray_group)
        # delete the gray/worm groups from the partitions now so we can test scenarios
        # for user whose group is missing.
        self.animal_partition.groups.pop()
        self.color_partition.groups.pop()

        # add a staff user, whose access will be unconditional in spite of group access.
        self.staff = StaffFactory.create(course_key=self.course.id)
Esempio n. 50
0
def _set_verification_partitions(course_key, icrv_blocks):
    """
    Create or update user partitions in the course.

    Ensures that each ICRV block in the course has an associated user partition
    with the groups ALLOW and DENY.

    Arguments:
        course_key (CourseKey): Identifier for the course.
        icrv_blocks (list of XBlock): In-course reverification blocks, e.g. reverification checkpoints.

    Returns:
        list of UserPartition
    """
    scheme = UserPartition.get_scheme(VERIFICATION_SCHEME_NAME)
    if scheme is None:
        log.error("Could not retrieve user partition scheme with ID %s", VERIFICATION_SCHEME_NAME)
        return []

    course = modulestore().get_course(course_key)
    if course is None:
        log.error("Could not find course %s", course_key)
        return []

    verified_partitions = course.get_user_partitions_for_scheme(scheme)
    partition_id_for_location = {
        p.parameters["location"]: p.id
        for p in verified_partitions
        if "location" in p.parameters
    }

    partitions = []
    for block in icrv_blocks:
        partition = UserPartition(
            id=partition_id_for_location.get(
                unicode(block.location),
                _unique_partition_id(course)
            ),
            name=block.related_assessment,
            description=u"Verification checkpoint at {}".format(block.related_assessment),
            scheme=scheme,
            parameters={"location": unicode(block.location)},
            groups=[
                Group(scheme.ALLOW, "Completed verification at {}".format(block.related_assessment)),
                Group(scheme.DENY, "Did not complete verification at {}".format(block.related_assessment)),
            ]
        )
        partitions.append(partition)

        log.info(
            (
                "Configured partition %s for course %s using a verified partition scheme "
                "for the in-course-reverification checkpoint at location %s"
            ),
            partition.id,
            course_key,
            partition.parameters["location"]
        )

    # Preserve existing, non-verified partitions from the course
    # Mark partitions for deleted in-course reverification as disabled.
    partitions += _other_partitions(verified_partitions, partitions, course_key)
    course.set_user_partitions_for_scheme(partitions, scheme)
    modulestore().update_item(course, ModuleStoreEnum.UserID.system)

    log.info("Saved updated partitions for the course %s", course_key)

    return partitions