def get_aggregate_exclusion_user_ids(course_key, roles=None): # pylint: disable=invalid-name """ This helper method will return the list of user ids that are marked in roles that can be excluded from certain aggregate queries. The list of roles to exclude can either be passed in roles argument or defined in a AGGREGATION_EXCLUDE_ROLES settings variable. """ cache_key = get_cache_key('exclude_users', unicode(course_key) + '_'.join(roles or 'None')) cached_data = cache.get(cache_key) if cached_data is not None: return cached_data exclude_user_ids = set() exclude_role_list = roles or getattr(settings, 'AGGREGATION_EXCLUDE_ROLES', [CourseStaffRole.ROLE]) for role in exclude_role_list: users = CourseRole(role, course_key).users_with_role() user_ids = set() for user in users: user_ids.add(user.id) exclude_user_ids = exclude_user_ids.union(user_ids) cache.set(cache_key, exclude_user_ids, 60 * 60) return exclude_user_ids
def test_group_name_case_insensitive(self): uppercase_loc = "i4x://ORG/COURSE/course/NAME" lowercase_loc = uppercase_loc.lower() lowercase_group = "role_org/course/name" uppercase_group = lowercase_group.upper() lowercase_user = UserFactory(groups=lowercase_group) uppercase_user = UserFactory(groups=uppercase_group) self.assertTrue( CourseRole("role", lowercase_loc).has_user(lowercase_user)) self.assertTrue( CourseRole("role", uppercase_loc).has_user(lowercase_user)) self.assertTrue( CourseRole("role", lowercase_loc).has_user(uppercase_user)) self.assertTrue( CourseRole("role", uppercase_loc).has_user(uppercase_user))
def check(self, user, instance=None): if not user.is_authenticated: return False if isinstance(instance, CourseKey): course_key = instance elif isinstance(instance, (CourseDescriptor, CourseOverview)): course_key = instance.id elif isinstance(instance, (ErrorDescriptor, XModule, XBlock)): course_key = instance.scope_ids.usage_id.course_key else: course_key = CourseKey.from_string(str(instance)) for role in self.roles: if CourseRole(role, course_key).has_user(user): return True if OrgRole(role, course_key.org).has_user(user): return True return False
def get_master_course(user=None, command=None): from contentstore.utils import add_instructor, initialize_permissions from courseware.courses import get_course_by_id from opaque_keys.edx.locations import SlashSeparatedCourseKey from student.roles import CourseRole from xmodule.modulestore.exceptions import InvalidLocationError if not user: user = User.objects.get(id=ADMIN_USER_ID) display_name = "LabsterX Master" org, number, run = COURSE_ID.split('/') try: course_key = SlashSeparatedCourseKey(org, number, run) fields = {'display_name': display_name} wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} fields.update(definition_data) if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() course = get_modulestore().create_course( course_key.org, course_key.course, course_key.run, user.id, fields=fields, ) # Make sure user has instructor and staff access to the new course add_instructor(course.id, user, user) # Initialize permissions for user in the new course initialize_permissions(course.id, user) command and command.stdout.write("name: {}\n".format(course.display_name)) except InvalidLocationError: course = get_course_by_id(course_key) return course
def test_group_name_case_sensitive(self): uppercase_course_id = "ORG/COURSE/NAME" lowercase_course_id = uppercase_course_id.lower() uppercase_course_key = SlashSeparatedCourseKey.from_deprecated_string(uppercase_course_id) lowercase_course_key = SlashSeparatedCourseKey.from_deprecated_string(lowercase_course_id) role = "role" lowercase_user = UserFactory() CourseRole(role, lowercase_course_key).add_users(lowercase_user) uppercase_user = UserFactory() CourseRole(role, uppercase_course_key).add_users(uppercase_user) self.assertTrue(CourseRole(role, lowercase_course_key).has_user(lowercase_user)) self.assertFalse(CourseRole(role, uppercase_course_key).has_user(lowercase_user)) self.assertFalse(CourseRole(role, lowercase_course_key).has_user(uppercase_user)) self.assertTrue(CourseRole(role, uppercase_course_key).has_user(uppercase_user))
def get_or_create_course(source, target, user): source_course = get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(source)) display_name = source_course.display_name org, number, run = target.split('/') course_key = SlashSeparatedCourseKey(org, number, run) fields = {'display_name': display_name} wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} fields.update(definition_data) try: if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() course = modulestore().create_course( course_key.org, course_key.course, course_key.run, user.id, fields=fields, ) except InvalidLocationError: course = get_course(course_key) else: # Make sure user has instructor and staff access to the new course add_instructor(course.id, user, user) # Initialize permissions for user in the new course initialize_permissions(course.id, user) return course
def create_new_course(request): """ Create a new course. Returns the URL for the course overview page. """ if not auth.has_access(request.user, CourseCreatorRole()): raise PermissionDenied() org = request.json.get('org') number = request.json.get('number') display_name = request.json.get('display_name') run = request.json.get('run') # allow/disable unicode characters in course_id according to settings if not settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID'): if _has_non_ascii_characters(org) or _has_non_ascii_characters(number) or _has_non_ascii_characters(run): return JsonResponse( {'error': _('Special characters not allowed in organization, course number, and course run.')}, status=400 ) try: course_key = SlashSeparatedCourseKey(org, number, run) # instantiate the CourseDescriptor and then persist it # note: no system to pass if display_name is None: metadata = {} else: metadata = {'display_name': display_name} # Set a unique wiki_slug for newly created courses. To maintain active wiki_slugs for # existing xml courses this cannot be changed in CourseDescriptor. # # TODO get rid of defining wiki slug in this org/course/run specific way and reconcile # w/ xmodule.course_module.CourseDescriptor.__init__ wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} # Create the course then fetch it from the modulestore # Check if role permissions group for a course named like this already exists # Important because role groups are case insensitive if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() fields = {} fields.update(definition_data) fields.update(metadata) # Creating the course raises InvalidLocationError if an existing course with this org/name is found new_course = modulestore('direct').create_course( course_key.org, course_key.offering, fields=fields, ) # can't use auth.add_users here b/c it requires request.user to already have Instructor perms in this course # however, we can assume that b/c this user had authority to create the course, the user can add themselves CourseInstructorRole(new_course.id).add_users(request.user) auth.add_users(request.user, CourseStaffRole(new_course.id), request.user) # seed the forums seed_permissions_roles(new_course.id) # auto-enroll the course creator in the course so that "View Live" will # work. CourseEnrollment.enroll(request.user, new_course.id) _users_assign_default_role(new_course.id) return JsonResponse({ 'url': reverse_course_url('course_handler', new_course.id) }) except InvalidLocationError: return JsonResponse({ 'ErrMsg': _( 'There is already a course defined with the same ' 'organization, course number, and course run. Please ' 'change either organization or course number to be unique.' ), 'OrgErrMsg': _( 'Please change either the organization or ' 'course number so that it is unique.'), 'CourseErrMsg': _( 'Please change either the organization or ' 'course number so that it is unique.'), }) except InvalidKeyError as error: return JsonResponse({ "ErrMsg": _("Unable to create course '{name}'.\n\n{err}").format(name=display_name, err=error.message)} )
def create_new_course(request): """ Create a new course. Returns the URL for the course overview page. """ if not auth.has_access(request.user, CourseCreatorRole()): raise PermissionDenied() org = request.json.get('org') number = request.json.get('number') display_name = request.json.get('display_name') run = request.json.get('run') # allow/disable unicode characters in course_id according to settings if not settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID'): if _has_non_ascii_characters(org) or _has_non_ascii_characters( number) or _has_non_ascii_characters(run): return JsonResponse( { 'error': _('Special characters not allowed in organization, course number, and course run.' ) }, status=400) try: course_key = SlashSeparatedCourseKey(org, number, run) # instantiate the CourseDescriptor and then persist it # note: no system to pass if display_name is None: metadata = {} else: metadata = {'display_name': display_name} # Set a unique wiki_slug for newly created courses. To maintain active wiki_slugs for # existing xml courses this cannot be changed in CourseDescriptor. # # TODO get rid of defining wiki slug in this org/course/run specific way and reconcile # w/ xmodule.course_module.CourseDescriptor.__init__ wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} # Create the course then fetch it from the modulestore # Check if role permissions group for a course named like this already exists # Important because role groups are case insensitive if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() fields = {} fields.update(definition_data) fields.update(metadata) # Creating the course raises InvalidLocationError if an existing course with this org/name is found new_course = modulestore('direct').create_course( course_key.org, course_key.offering, fields=fields, ) # can't use auth.add_users here b/c it requires request.user to already have Instructor perms in this course # however, we can assume that b/c this user had authority to create the course, the user can add themselves CourseInstructorRole(new_course.id).add_users(request.user) auth.add_users(request.user, CourseStaffRole(new_course.id), request.user) # seed the forums seed_permissions_roles(new_course.id) # auto-enroll the course creator in the course so that "View Live" will # work. CourseEnrollment.enroll(request.user, new_course.id) _users_assign_default_role(new_course.id) return JsonResponse( {'url': reverse_course_url('course_handler', new_course.id)}) except InvalidLocationError: return JsonResponse({ 'ErrMsg': _('There is already a course defined with the same ' 'organization, course number, and course run. Please ' 'change either organization or course number to be unique.'), 'OrgErrMsg': _('Please change either the organization or ' 'course number so that it is unique.'), 'CourseErrMsg': _('Please change either the organization or ' 'course number so that it is unique.'), }) except InvalidKeyError as error: return JsonResponse({ "ErrMsg": _("Unable to create course '{name}'.\n\n{err}").format( name=display_name, err=error.message) })
def force_create_course(source, target, user, extra_fields=None): source_course_key = SlashSeparatedCourseKey.from_deprecated_string(source) source_course = get_course_by_id(source_course_key) display_name = source_course.display_name fields = {'display_name': display_name} # duplicated_fields = [ # 'key_dates', 'video', # 'course_staff_short', 'course_staff_extended', # 'requirements', 'textbook', 'faq', 'more_info', # 'number', 'instructors', 'end_date', # 'prerequisites', 'ocw_links', # ] # for field in duplicated_fields: # fields[field] = getattr(source_course, field) course = None start_index = 0 org, original_number, run = target.split('/') number = original_number while course is None: course_key = SlashSeparatedCourseKey(org, number, run) wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} fields.update(definition_data) if extra_fields: fields.update(extra_fields) try: if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() course = modulestore().create_course( course_key.org, course_key.course, course_key.run, user.id, fields=fields, ) except InvalidLocationError: start_index += 1 number = "{}{}".format(original_number, start_index) continue else: # Make sure user has instructor and staff access to the new course add_instructor(course.id, user, user) # Initialize permissions for user in the new course initialize_permissions(course.id, user) copy_about_fields(user, source_course_key, course_key, course) UserProfile.objects\ .filter(user_id=user.id)\ .exclude(user_type=UserProfile.USER_TYPE_TEACHER)\ .update(user_type=UserProfile.USER_TYPE_TEACHER) return course