Automatically add master's to the group access of verified content
This commit is contained in:
@@ -1,14 +1,25 @@
|
||||
""" Helper methods for CourseModes. """
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from student.helpers import VERIFY_STATUS_APPROVED, VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED
|
||||
from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID
|
||||
|
||||
|
||||
DISPLAY_VERIFIED = "verified"
|
||||
DISPLAY_HONOR = "honor"
|
||||
DISPLAY_AUDIT = "audit"
|
||||
DISPLAY_PROFESSIONAL = "professional"
|
||||
|
||||
MASTERS_ID = settings.COURSE_ENROLLMENT_MODES.get('masters', {}).get('id', None)
|
||||
VERIFIED_ID = settings.COURSE_ENROLLMENT_MODES['verified']['id']
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def enrollment_mode_display(mode, verification_status, course_id):
|
||||
""" Select appropriate display strings and CSS classes.
|
||||
@@ -80,3 +91,31 @@ def _enrollment_mode_display(enrollment_mode, verification_status, course_id):
|
||||
display_mode = enrollment_mode
|
||||
|
||||
return display_mode
|
||||
|
||||
|
||||
def update_masters_access(item):
|
||||
"""
|
||||
Update the XBlock's group access to allow the master's group,
|
||||
in addition to the verified content group.
|
||||
"""
|
||||
group_access = item.group_access
|
||||
enrollment_groups = group_access.get(ENROLLMENT_TRACK_PARTITION_ID, None)
|
||||
if enrollment_groups is not None:
|
||||
if VERIFIED_ID in enrollment_groups and MASTERS_ID not in enrollment_groups:
|
||||
enrollment_groups.append(MASTERS_ID)
|
||||
item.group_access = group_access
|
||||
return True
|
||||
|
||||
|
||||
def update_masters_access_course(store, course_id, user_id):
|
||||
"""
|
||||
Update all blocks in the verified content group to include the master's content group
|
||||
"""
|
||||
|
||||
with store.bulk_operations(course_id):
|
||||
items = store.get_items(course_id, settings={'group_access': {'$exists': True}}, include_orphans=False)
|
||||
for item in items:
|
||||
if update_masters_access(item):
|
||||
log.info("Publishing %s with Master's group access", item.location)
|
||||
store.update_item(item, user_id)
|
||||
store.publish(item.location, user_id)
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
"""
|
||||
Signal handler for setting default course mode expiration dates
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from crum import get_current_user
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch.dispatcher import receiver
|
||||
|
||||
from xmodule.modulestore.django import SignalHandler, modulestore
|
||||
|
||||
from .helpers import update_masters_access_course
|
||||
from .models import CourseMode, CourseModeExpirationConfig
|
||||
|
||||
|
||||
@@ -35,3 +41,15 @@ def _listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable
|
||||
def _should_update_date(verified_mode):
|
||||
""" Returns whether or not the verified mode should be updated. """
|
||||
return not(verified_mode is None or verified_mode.expiration_datetime_is_explicit)
|
||||
|
||||
|
||||
@receiver(post_save, sender=CourseMode)
|
||||
def update_access_for_masters_mode(sender, instance=None, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Adds master's access to verified content when the master's mode is created
|
||||
"""
|
||||
if instance.mode_slug != CourseMode.MASTERS:
|
||||
return
|
||||
user = get_current_user()
|
||||
user_id = user.id if user else None
|
||||
update_masters_access_course(modulestore(), instance.course_id, user_id)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Unit tests for the course_mode signals
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
@@ -10,8 +11,9 @@ from pytz import UTC
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from course_modes.signals import _listen_for_course_publish
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -87,3 +89,28 @@ class CourseModeSignalTest(ModuleStoreTestCase):
|
||||
course_mode.refresh_from_db()
|
||||
|
||||
self.assertEqual(course_mode.expiration_datetime, self.end - timedelta(days=verification_window))
|
||||
|
||||
def test_masters_mode(self):
|
||||
# create an xblock with verified group access
|
||||
verified_section = ItemFactory.create(
|
||||
category="sequential",
|
||||
metadata={'group_access': {50: [2]}}
|
||||
)
|
||||
# and a section with no restriction
|
||||
section2 = ItemFactory.create(
|
||||
category="sequential",
|
||||
)
|
||||
section3 = ItemFactory.create(
|
||||
category='sequential',
|
||||
metadata={'group_access': {50: [1]}}
|
||||
)
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
|
||||
# create the master's mode. signal will add masters to the verified section
|
||||
self.create_mode('masters', 'masters')
|
||||
verified_section_ret = self.store.get_item(verified_section.location)
|
||||
section2_ret = self.store.get_item(section2.location)
|
||||
section3_ret = self.store.get_item(section3.location)
|
||||
# group 2 is verified. 7 is masters
|
||||
assert verified_section_ret.group_access[50] == [2, 7]
|
||||
assert section2_ret.group_access == {}
|
||||
assert section2_ret.group_access == {50: [1]}
|
||||
|
||||
Reference in New Issue
Block a user