def filtered_list(cls): """ Filter fields based on feature flag, i.e. enabled, disabled. """ # Copy the filtered list to avoid permanently changing the class attribute. filtered_list = list(cls.FILTERED_LIST) # Do not show giturl if feature is not enabled. if not settings.FEATURES.get('ENABLE_EXPORT_GIT'): filtered_list.append('giturl') # Do not show edxnotes if the feature is disabled. if not settings.FEATURES.get('ENABLE_EDXNOTES'): filtered_list.append('edxnotes') # Do not show video_upload_pipeline if the feature is disabled. if not settings.FEATURES.get('ENABLE_VIDEO_UPLOAD_PIPELINE'): filtered_list.append('video_upload_pipeline') # Do not show social sharing url field if the feature is disabled. if (not hasattr(settings, 'SOCIAL_SHARING_SETTINGS') or not getattr(settings, 'SOCIAL_SHARING_SETTINGS', {}).get("CUSTOM_COURSE_URLS")): filtered_list.append('social_sharing_url') # Do not show teams configuration if feature is disabled. if not settings.FEATURES.get('ENABLE_TEAMS'): filtered_list.append('teams_configuration') if not settings.FEATURES.get('ENABLE_VIDEO_BUMPER'): filtered_list.append('video_bumper') # Do not show enable_ccx if feature is not enabled. if not settings.FEATURES.get('CUSTOM_COURSES_EDX'): filtered_list.append('enable_ccx') filtered_list.append('ccx_connector') # Do not show "Issue Open Badges" in Studio Advanced Settings # if the feature is disabled. if not settings.FEATURES.get('ENABLE_OPENBADGES'): filtered_list.append('issue_badges') # If the XBlockStudioConfiguration table is not being used, there is no need to # display the "Allow Unsupported XBlocks" setting. if not XBlockStudioConfigurationFlag.is_enabled(): filtered_list.append('allow_unsupported_xblocks') # TODO: https://openedx.atlassian.net/browse/EDUCATOR-736 # Before we roll out the auto-certs feature, move this to a good, shared # place such that we're not repeating code found in LMS. switches = WaffleSwitchNamespace(name=u'certificates', log_prefix=u'Certificates: ') if not switches.is_enabled(u'instructor_paced_only'): filtered_list.append('certificate_available_date') return filtered_list
def filtered_list(cls): """ Filter fields based on feature flag, i.e. enabled, disabled. """ # Copy the filtered list to avoid permanently changing the class attribute. filtered_list = list(cls.FILTERED_LIST) # Do not show giturl if feature is not enabled. if not settings.FEATURES.get('ENABLE_EXPORT_GIT'): filtered_list.append('giturl') # Do not show edxnotes if the feature is disabled. if not settings.FEATURES.get('ENABLE_EDXNOTES'): filtered_list.append('edxnotes') # Do not show video_upload_pipeline if the feature is disabled. if not settings.FEATURES.get('ENABLE_VIDEO_UPLOAD_PIPELINE'): filtered_list.append('video_upload_pipeline') # Do not show social sharing url field if the feature is disabled. if (not hasattr(settings, 'SOCIAL_SHARING_SETTINGS') or not getattr(settings, 'SOCIAL_SHARING_SETTINGS', {}).get("CUSTOM_COURSE_URLS")): filtered_list.append('social_sharing_url') # Do not show teams configuration if feature is disabled. if not settings.FEATURES.get('ENABLE_TEAMS'): filtered_list.append('teams_configuration') if not settings.FEATURES.get('ENABLE_VIDEO_BUMPER'): filtered_list.append('video_bumper') # Do not show enable_ccx if feature is not enabled. if not settings.FEATURES.get('CUSTOM_COURSES_EDX'): filtered_list.append('enable_ccx') filtered_list.append('ccx_connector') # Do not show "Issue Open Badges" in Studio Advanced Settings # if the feature is disabled. if not settings.FEATURES.get('ENABLE_OPENBADGES'): filtered_list.append('issue_badges') # If the XBlockStudioConfiguration table is not being used, there is no need to # display the "Allow Unsupported XBlocks" setting. if not XBlockStudioConfigurationFlag.is_enabled(): filtered_list.append('allow_unsupported_xblocks') # TODO: https://openedx.atlassian.net/browse/EDUCATOR-736 # Before we roll out the auto-certs feature, move this to a good, shared # place such that we're not repeating code found in LMS. switches = WaffleSwitchNamespace(name=u'certificates', log_prefix=u'Certificates: ') if not switches.is_enabled(u'instructor_paced_only'): filtered_list.append('certificate_available_date') return filtered_list
def test_create_schedule(self): """ A schedule should be created for every new enrollment if the switch is active. """ SWITCH_NAME = 'enable-create-schedule-receiver' switch_namesapce = WaffleSwitchNamespace('schedules') with switch_namesapce.override(SWITCH_NAME, True): enrollment = CourseEnrollmentFactory() self.assertIsNotNone(enrollment.schedule) with switch_namesapce.override(SWITCH_NAME, False): enrollment = CourseEnrollmentFactory() with self.assertRaises(Schedule.DoesNotExist): enrollment.schedule
def create_schedule(sender, **kwargs): if WaffleSwitchNamespace('schedules').is_enabled( 'enable-create-schedule-receiver') and kwargs['created']: enrollment = kwargs['instance'] upgrade_deadline = _get_upgrade_deadline(enrollment) Schedule.objects.create(enrollment=enrollment, start=timezone.now(), upgrade_deadline=upgrade_deadline)
def setUp(self): """ Add courses with the end date set to various values """ super(TestCourseIndexArchived, self).setUp() # Base course has no end date (so is active) self.course.end = None self.course.display_name = 'Active Course 1' self.ORG = self.course.location.org self.save_course() # Active course has end date set to tomorrow self.active_course = CourseFactory.create( display_name='Active Course 2', org=self.ORG, end=self.TOMORROW, ) # Archived course has end date set to yesterday self.archived_course = CourseFactory.create( display_name='Archived Course', org=self.ORG, end=self.YESTERDAY, ) # Base user has global staff access self.assertTrue(GlobalStaff().has_user(self.user)) # Staff user just has course staff access self.staff, self.staff_password = self.create_non_staff_user() for course in (self.course, self.active_course, self.archived_course): CourseStaffRole(course.id).add_users(self.staff) # Make sure we've cached data which could change the query counts # depending on test execution order WaffleSwitchNamespace(name=COURSE_WAFFLE_NAMESPACE).is_enabled( u'enable_global_staff_optimization') WaffleSwitchNamespace( name=STUDIO_WAFFLE_NAMESPACE).is_enabled(u'enable_policy_page') WaffleSwitchNamespace(name=DJANGO_UTILS_NAMESPACE).is_enabled( u'enable_memory_middleware')
def waffle(): """ Returns the namespaced, cached, audited Waffle class for open_edx_util. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'OpenEdX Util: ')
def waffle_switch(): """ Returns the namespaced, cached, audited Waffle class for course experience. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix='course_experience: ')
def waffle(): """ Returns the namespaced, cached, audited Waffle Switch class for Studio pages. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Studio: ')
""" This module contains various configuration settings via waffle switches for the instructor_task app. """ from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace, WaffleSwitchNamespace WAFFLE_NAMESPACE = u'instructor_task' INSTRUCTOR_TASK_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace( name=WAFFLE_NAMESPACE) WAFFLE_SWITCHES = WaffleSwitchNamespace(name=WAFFLE_NAMESPACE) # Waffle switches OPTIMIZE_GET_LEARNERS_FOR_COURSE = u'optimize_get_learners_for_course' GENERATE_GRADE_REPORT_VERIFIED_ONLY = u'generate_grade_report_for_verified_only' def waffle_flags(): """ Returns the namespaced, cached, audited Waffle flags dictionary for Grades. """ return {} def optimize_get_learners_switch_enabled(): """ Returns True if optimize get learner switch is enabled, otherwise False. """ return WAFFLE_SWITCHES.is_enabled(OPTIMIZE_GET_LEARNERS_FOR_COURSE)
def waffle(): """ Returns the namespaced, cached, audited shared Waffle Switch class. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Course Experience: ')
""" Platform support for Programs. This package is a thin wrapper around interactions with the Programs service, supporting learner- and author-facing features involving that service if and only if the service is deployed in the Open edX installation. To ensure maximum separation of concerns, and a minimum of interdependencies, this package should be kept small, thin, and stateless. """ from openedx.core.djangoapps.waffle_utils import (WaffleSwitch, WaffleSwitchNamespace) PROGRAMS_WAFFLE_SWITCH_NAMESPACE = WaffleSwitchNamespace(name='programs') # This is meant to be enabled until https://openedx.atlassian.net/browse/LEARNER-5573 needs to be resolved ALWAYS_CALCULATE_PROGRAM_PRICE_AS_ANONYMOUS_USER = WaffleSwitch( PROGRAMS_WAFFLE_SWITCH_NAMESPACE, 'always_calculate_program_price_as_anonymous_user')
def waffle(): """ Returns the namespaced, cached, audited Waffle class for user_api. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'UserAPI: ')
def waffle(): """ Returns the namespaced, cached, audited Waffle class for completion. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix='completion: ')
def _is_enabled(self): """ Returns whether this middleware is enabled. """ return WaffleSwitchNamespace( name=WAFFLE_NAMESPACE).is_enabled(u'enable_memory_middleware')
""" Course API """ from openedx.core.djangoapps.waffle_utils import WaffleSwitch, WaffleSwitchNamespace WAFFLE_SWITCH_NAMESPACE = WaffleSwitchNamespace( name='course_list_api_rate_limit') # .. toggle_name: course_list_api_rate_limit.rate_limit_2 # .. toggle_implementation: WaffleSwitch # .. toggle_default: False # .. toggle_description: Waffle switch to enable the throttling of 2 requests/minute to the course API. For staff # users, this limit is 10 requests/minute. # .. toggle_use_cases: circuit_breaker # .. toggle_creation_date: 2018-06-12 # .. toggle_tickets: https://openedx.atlassian.net/browse/LEARNER-5527 USE_RATE_LIMIT_2_FOR_COURSE_LIST_API = WaffleSwitch(WAFFLE_SWITCH_NAMESPACE, 'rate_limit_2', __name__) # .. toggle_name: course_list_api_rate_limit.rate_limit_10 # .. toggle_implementation: WaffleSwitch # .. toggle_default: False # .. toggle_description: Waffle switch to enable the throttling of 10 requests/minute to the course API. For staff # users, this limit is 20 requests/minute. # .. toggle_use_cases: circuit_breaker # .. toggle_creation_date: 2018-06-12 # .. toggle_tickets: https://openedx.atlassian.net/browse/LEARNER-5527 USE_RATE_LIMIT_10_FOR_COURSE_LIST_API = WaffleSwitch(WAFFLE_SWITCH_NAMESPACE, 'rate_limit_10', __name__)
def _create_courseware_context(self, request): """ Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ course_url_name = default_course_url_name(self.course.id) course_url = reverse( course_url_name, kwargs={'course_id': six.text_type(self.course.id)}) show_search = ( settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH') or (settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH_FOR_COURSE_STAFF') and self.is_staff)) staff_access = self.is_staff reset_deadlines_url = reverse( 'openedx.course_experience.reset_course_deadlines', kwargs={'course_id': six.text_type(self.course.id)}) allow_anonymous = allow_public_access(self.course, [COURSE_VISIBILITY_PUBLIC]) display_reset_dates_banner = False if not allow_anonymous and RELATIVE_DATES_FLAG.is_enabled( self.course.id): # pylint: disable=too-many-nested-blocks course_overview = CourseOverview.objects.get( id=str(self.course_key)) end_date = getattr(course_overview, 'end_date') if course_overview.self_paced and (not end_date or timezone.now() < end_date): if (CourseEnrollment.objects.filter( course=course_overview, user=request.user, mode=CourseMode.VERIFIED).exists()): course_block_tree = get_course_outline_block_tree( request, str(self.course_key), request.user) course_sections = course_block_tree.get('children', []) for section in course_sections: if display_reset_dates_banner: break for subsection in section.get('children', []): if (not subsection.get('complete', True) and subsection.get( 'due', timezone.now() + timedelta(1)) < timezone.now()): display_reset_dates_banner = True break courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'course': self.course, 'course_url': course_url, 'chapter': self.chapter, 'section': self.section, 'init': '', 'fragment': Fragment(), 'staff_access': staff_access, 'can_masquerade': self.can_masquerade, 'masquerade': self.masquerade, 'supports_preview_menu': True, 'studio_url': get_studio_url(self.course, 'course'), 'xqa_server': settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"), 'bookmarks_api_url': reverse('bookmarks'), 'language_preference': self._get_language_preference(), 'disable_optimizely': not WaffleSwitchNamespace('RET').is_enabled( 'enable_optimizely_in_courseware'), 'section_title': None, 'sequence_title': None, 'disable_accordion': COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id), 'show_search': show_search, 'relative_dates_is_enabled': RELATIVE_DATES_FLAG.is_enabled(self.course.id), 'reset_deadlines_url': reset_deadlines_url, 'display_reset_dates_banner': display_reset_dates_banner, } courseware_context.update( get_experiment_user_metadata_context( self.course, self.effective_user, )) table_of_contents = toc_for_course( self.effective_user, self.request, self.course, self.chapter_url_name, self.section_url_name, self.field_data_cache, ) courseware_context['accordion'] = render_accordion( self.request, self.course, table_of_contents['chapters'], ) courseware_context['course_sock_fragment'] = CourseSockFragmentView( ).render_to_fragment(request, course=self.course_overview) # entrance exam data self._add_entrance_exam_to_context(courseware_context) if self.section: # chromeless data if self.section.chrome: chrome = [ s.strip() for s in self.section.chrome.lower().split(",") ] if 'accordion' not in chrome: courseware_context['disable_accordion'] = True if 'tabs' not in chrome: courseware_context['disable_tabs'] = True # default tab if self.section.default_tab: courseware_context['default_tab'] = self.section.default_tab # section data courseware_context[ 'section_title'] = self.section.display_name_with_default section_context = self._create_section_context( table_of_contents['previous_of_active_section'], table_of_contents['next_of_active_section'], ) courseware_context['fragment'] = self.section.render( self.view, section_context) if self.section.position and self.section.has_children: self._add_sequence_title_to_context(courseware_context) # Courseware MFE link if show_courseware_mfe_link(request.user, staff_access, self.course.id): if self.section: try: unit_key = UsageKey.from_string( request.GET.get('activate_block_id', '')) # `activate_block_id` is typically a Unit (a.k.a. Vertical), # but it can technically be any block type. Do a check to # make sure it's really a Unit before we use it for the MFE. if unit_key.block_type != 'vertical': unit_key = None except InvalidKeyError: unit_key = None courseware_context[ 'microfrontend_link'] = get_microfrontend_url( self.course.id, self.section.location, unit_key) else: courseware_context[ 'microfrontend_link'] = get_microfrontend_url( self.course.id) else: courseware_context['microfrontend_link'] = None return courseware_context
""" Waffle flags and switches for user authn. """ from openedx.core.djangoapps.waffle_utils import WaffleSwitch, WaffleSwitchNamespace _WAFFLE_NAMESPACE = u'user_authn' _WAFFLE_SWITCH_NAMESPACE = WaffleSwitchNamespace(name=_WAFFLE_NAMESPACE, log_prefix=u'UserAuthN: ') # .. toggle_name: user_authn.enable_login_using_thirdparty_auth_only # .. toggle_implementation: WaffleSwitch # .. toggle_default: False # .. toggle_description: When enabled, users must be sign in using their allowed domain SSO account. This includes sign- # ins to the Django admin dashboard at "/admin". # .. toggle_use_cases: temporary # .. toggle_creation_date: 2019-11-20 # .. toggle_target_removal_date: 2020-01-31 # .. toggle_warnings: Requires THIRD_PARTY_AUTH_ONLY_DOMAIN to also be set. # .. toggle_tickets: ENT-2461 ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY = WaffleSwitch( _WAFFLE_SWITCH_NAMESPACE, 'enable_login_using_thirdparty_auth_only', __name__)
def _is_switch_enabled(name): return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE).is_enabled(name)
def waffle(): """ Returns the namespaced, cached, audited Waffle class for Accessibility Accomodation Request Page. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Accessibility: ')
def _create_courseware_context(self, request): """ Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ course_url_name = default_course_url_name(request) course_url = reverse(course_url_name, kwargs={'course_id': unicode(self.course.id)}) courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'course': self.course, 'course_url': course_url, 'chapter': self.chapter, 'section': self.section, 'init': '', 'fragment': Fragment(), 'staff_access': self.is_staff, 'masquerade': self.masquerade, 'supports_preview_menu': True, 'studio_url': get_studio_url(self.course, 'course'), 'xqa_server': settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"), 'bookmarks_api_url': reverse('bookmarks'), 'language_preference': self._get_language_preference(), 'disable_optimizely': not WaffleSwitchNamespace('RET').is_enabled( 'enable_optimizely_in_courseware'), 'section_title': None, 'sequence_title': None, 'disable_accordion': waffle.flag_is_active(request, UNIFIED_COURSE_VIEW_FLAG), # TODO: (Experimental Code). See https://openedx.atlassian.net/wiki/display/RET/2.+In-course+Verification+Prompts 'upgrade_link': check_and_get_upgrade_link(request, self.effective_user, self.course.id), 'upgrade_price': get_cosmetic_verified_display_price(self.course), # ENDTODO } table_of_contents = toc_for_course( self.effective_user, self.request, self.course, self.chapter_url_name, self.section_url_name, self.field_data_cache, ) courseware_context['accordion'] = render_accordion( self.request, self.course, table_of_contents['chapters'], ) courseware_context['course_sock_fragment'] = CourseSockFragmentView( ).render_to_fragment(request, course=self.course) # entrance exam data self._add_entrance_exam_to_context(courseware_context) # staff masquerading data if not is_course_open_for_learner(self.effective_user, self.course): # Disable student view button if user is staff and # course is not yet visible to students. courseware_context['disable_student_access'] = True courseware_context['supports_preview_menu'] = False if self.section: # chromeless data if self.section.chrome: chrome = [ s.strip() for s in self.section.chrome.lower().split(",") ] if 'accordion' not in chrome: courseware_context['disable_accordion'] = True if 'tabs' not in chrome: courseware_context['disable_tabs'] = True # default tab if self.section.default_tab: courseware_context['default_tab'] = self.section.default_tab # section data courseware_context[ 'section_title'] = self.section.display_name_with_default section_context = self._create_section_context( table_of_contents['previous_of_active_section'], table_of_contents['next_of_active_section'], ) courseware_context['fragment'] = self.section.render( STUDENT_VIEW, section_context) if self.section.position and self.section.has_children: display_items = self.section.get_display_items() if display_items: try: courseware_context['sequence_title'] = display_items[self.section.position - 1] \ .display_name_with_default except IndexError: log.exception( "IndexError loading courseware for user %s, course %s, section %s, position %d. Total items: %d. URL: %s", self.real_user.username, self.course.id, self.section.display_name_with_default, self.section.position, len(display_items), self.url, ) raise return courseware_context
""" Feature toggle code for oauth_dispatch. """ from __future__ import absolute_import from edx_rest_framework_extensions.config import OAUTH_TOGGLE_NAMESPACE, SWITCH_ENFORCE_JWT_SCOPES from openedx.core.djangoapps.waffle_utils import WaffleSwitch, WaffleSwitchNamespace ENFORCE_JWT_SCOPES = WaffleSwitch( WaffleSwitchNamespace(name=OAUTH_TOGGLE_NAMESPACE), SWITCH_ENFORCE_JWT_SCOPES)
""" This module contains various configuration settings via waffle switches for the course_details view. """ from openedx.core.djangoapps.waffle_utils import (CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace) COURSE_DETAIL_WAFFLE_NAMESPACE = 'course_detail' COURSE_DETAIL_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace( name=COURSE_DETAIL_WAFFLE_NAMESPACE) WAFFLE_SWITCHES = WaffleSwitchNamespace(name=COURSE_DETAIL_WAFFLE_NAMESPACE) # Course Override Flag COURSE_DETAIL_UPDATE_CERTIFICATE_DATE = u'course_detail_update_certificate_date' def waffle_flags(): """ Returns the namespaced, cached, audited Waffle flags dictionary for course detail. """ return { COURSE_DETAIL_UPDATE_CERTIFICATE_DATE: CourseWaffleFlag( waffle_namespace=COURSE_DETAIL_WAFFLE_NAMESPACE, flag_name=COURSE_DETAIL_UPDATE_CERTIFICATE_DATE, flag_undefined_default=False, ) }
def _create_courseware_context(self, request): """ Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ from lms.urls import RESET_COURSE_DEADLINES_NAME course_url_name = default_course_url_name(self.course.id) course_url = reverse( course_url_name, kwargs={'course_id': six.text_type(self.course.id)}) show_search = ( settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH') or (settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH_FOR_COURSE_STAFF') and self.is_staff)) staff_access = self.is_staff allow_anonymous = check_public_access(self.course, [COURSE_VISIBILITY_PUBLIC]) display_reset_dates_banner = False if not allow_anonymous and RELATIVE_DATES_FLAG.is_enabled( self.course.id): display_reset_dates_banner = reset_deadlines_banner_should_display( self.course_key, request) reset_deadlines_url = reverse(RESET_COURSE_DEADLINES_NAME ) if display_reset_dates_banner else None reset_deadlines_redirect_url_base = COURSE_HOME_VIEW_NAME if reset_deadlines_url else None courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'course': self.course, 'course_url': course_url, 'chapter': self.chapter, 'section': self.section, 'init': '', 'fragment': Fragment(), 'staff_access': staff_access, 'can_masquerade': self.can_masquerade, 'masquerade': self.masquerade, 'supports_preview_menu': True, 'studio_url': get_studio_url(self.course, 'course'), 'xqa_server': settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"), 'bookmarks_api_url': reverse('bookmarks'), 'language_preference': self._get_language_preference(), 'disable_optimizely': not WaffleSwitchNamespace('RET').is_enabled( 'enable_optimizely_in_courseware'), 'section_title': None, 'sequence_title': None, 'disable_accordion': COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id), 'show_search': show_search, 'relative_dates_is_enabled': RELATIVE_DATES_FLAG.is_enabled(self.course.id), 'display_reset_dates_banner': display_reset_dates_banner, 'reset_deadlines_url': reset_deadlines_url, 'reset_deadlines_redirect_url_base': reset_deadlines_redirect_url_base, 'reset_deadlines_redirect_url_id_dict': { 'course_id': str(self.course.id) }, } courseware_context.update( get_experiment_user_metadata_context( self.course, self.effective_user, )) table_of_contents = toc_for_course( self.effective_user, self.request, self.course, self.chapter_url_name, self.section_url_name, self.field_data_cache, ) courseware_context['accordion'] = render_accordion( self.request, self.course, table_of_contents['chapters'], ) courseware_context['course_sock_fragment'] = CourseSockFragmentView( ).render_to_fragment(request, course=self.course) # entrance exam data self._add_entrance_exam_to_context(courseware_context) if self.section: # chromeless data if self.section.chrome: chrome = [ s.strip() for s in self.section.chrome.lower().split(",") ] if 'accordion' not in chrome: courseware_context['disable_accordion'] = True if 'tabs' not in chrome: courseware_context['disable_tabs'] = True # default tab if self.section.default_tab: courseware_context['default_tab'] = self.section.default_tab # section data courseware_context[ 'section_title'] = self.section.display_name_with_default section_context = self._create_section_context( table_of_contents['previous_of_active_section'], table_of_contents['next_of_active_section'], ) courseware_context['fragment'] = self.section.render( self.view, section_context) if self.section.position and self.section.has_children: self._add_sequence_title_to_context(courseware_context) # Courseware MFE link if show_courseware_mfe_link(request.user, staff_access, self.course.id): courseware_context['microfrontend_link'] = self.microfrontend_url else: courseware_context['microfrontend_link'] = None return courseware_context
def waffle(): """ Returns the namespaced and cached Waffle class for BlockStructures. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'BlockStructure: ')
from opaque_keys.edx.keys import CourseKey from openedx.core.djangoapps.user_api.accounts.image_helpers import ( _get_default_profile_image_urls, _get_profile_image_urls, _make_profile_image_name, get_profile_image_storage) from openedx.core.djangoapps.user_api.accounts.serializers import PROFILE_IMAGE_KEY_PREFIX from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace from PIL import Image from rest_framework.exceptions import ParseError from student.roles import CourseObserverRole, CourseRole USER_METRICS_CACHE_TTL = 60 * 60 COURSE_METRICS_CACHE_TTL = 30 * 60 COHORT_NAMESPACE = 'course_groups' COHORT_SWITCH = 'enable_apros_integration' WAFFLE_COHORT_SWITCHES = WaffleSwitchNamespace(name=COHORT_NAMESPACE) def address_exists_in_network(ip_address, net_n_bits): """ return True if the ip address exists in the subnet address otherwise return False """ ip_address = struct.unpack('<L', socket.inet_aton(ip_address))[0] net, bits = net_n_bits.split('/') net_address = struct.unpack('<L', socket.inet_aton(net))[0] net_mask = ((1 << int(bits)) - 1) return ip_address & net_mask == net_address & net_mask def get_client_ip_address(request):
def _create_courseware_context(self, request): """ Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ course_url_name = default_course_url_name(self.course.id) course_url = reverse(course_url_name, kwargs={'course_id': unicode(self.course.id)}) courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'course': self.course, 'course_url': course_url, 'chapter': self.chapter, 'section': self.section, 'init': '', 'fragment': Fragment(), 'staff_access': self.is_staff, 'masquerade': self.masquerade, 'supports_preview_menu': True, 'studio_url': get_studio_url(self.course, 'course'), 'xqa_server': settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"), 'bookmarks_api_url': reverse('bookmarks'), 'language_preference': self._get_language_preference(), 'disable_optimizely': not WaffleSwitchNamespace('RET').is_enabled( 'enable_optimizely_in_courseware'), 'section_title': None, 'sequence_title': None, 'disable_accordion': COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id), } courseware_context.update( get_experiment_user_metadata_context( self.course, self.effective_user, )) table_of_contents = toc_for_course( self.effective_user, self.request, self.course, self.chapter_url_name, self.section_url_name, self.field_data_cache, ) courseware_context['accordion'] = render_accordion( self.request, self.course, table_of_contents['chapters'], ) courseware_context['course_sock_fragment'] = CourseSockFragmentView( ).render_to_fragment(request, course=self.course) # entrance exam data self._add_entrance_exam_to_context(courseware_context) if self.section: # chromeless data if self.section.chrome: chrome = [ s.strip() for s in self.section.chrome.lower().split(",") ] if 'accordion' not in chrome: courseware_context['disable_accordion'] = True if 'tabs' not in chrome: courseware_context['disable_tabs'] = True # default tab if self.section.default_tab: courseware_context['default_tab'] = self.section.default_tab # section data courseware_context[ 'section_title'] = self.section.display_name_with_default section_context = self._create_section_context( table_of_contents['previous_of_active_section'], table_of_contents['next_of_active_section'], ) courseware_context['fragment'] = self.section.render( self.view, section_context) if self.section.position and self.section.has_children: self._add_sequence_title_to_context(courseware_context) return courseware_context
""" Contains configuration for schedules app """ from openedx.core.djangoapps.waffle_utils import ( WaffleFlagNamespace, CourseWaffleFlag, WaffleFlag, WaffleSwitch, WaffleSwitchNamespace, ) WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name=u'schedules') WAFFLE_SWITCH_NAMESPACE = WaffleSwitchNamespace(name=u'schedules') CREATE_SCHEDULE_WAFFLE_FLAG = CourseWaffleFlag( waffle_namespace=WAFFLE_FLAG_NAMESPACE, flag_name=u'create_schedules_for_course', ) COURSE_UPDATE_WAFFLE_FLAG = CourseWaffleFlag( waffle_namespace=WAFFLE_FLAG_NAMESPACE, flag_name=u'send_updates_for_course', ) DEBUG_MESSAGE_WAFFLE_FLAG = WaffleFlag(WAFFLE_FLAG_NAMESPACE, u'enable_debugging') COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH = WaffleSwitch( WAFFLE_SWITCH_NAMESPACE, u'course_update_show_unsubscribe')
""" Enrollment API helpers and settings """ from openedx.core.djangoapps.waffle_utils import (WaffleSwitch, WaffleSwitchNamespace) WAFFLE_SWITCH_NAMESPACE = WaffleSwitchNamespace( name='enrollment_api_rate_limit') USE_RATE_LIMIT_400_FOR_STAFF_FOR_ENROLLMENT_API = WaffleSwitch( WAFFLE_SWITCH_NAMESPACE, 'staff_rate_limit_400') USE_RATE_LIMIT_100_FOR_STAFF_FOR_ENROLLMENT_API = WaffleSwitch( WAFFLE_SWITCH_NAMESPACE, 'staff_rate_limit_100') USE_RATE_LIMIT_40_FOR_ENROLLMENT_API = WaffleSwitch(WAFFLE_SWITCH_NAMESPACE, 'rate_limit_40')
""" Student app helpers and settings """ from __future__ import absolute_import from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace # Namespace for student app waffle switches STUDENT_WAFFLE_NAMESPACE = WaffleSwitchNamespace(name='student')
def waffle(): """ Returns the namespaced, cached, audited Waffle class for Certificates. """ return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Certificates: ')
""" Waffle flags and switches for user authn. """ from __future__ import absolute_import from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace WAFFLE_NAMESPACE = u'user_authn' # If this switch is enabled then users must be sign in using their allowed domain SSO account ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY = 'enable_login_using_thirdparty_auth_only' waffle = WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'UserAuthN: ')