def configure_waffle_namespace(feature_enabled): namespace = certs_waffle.waffle() auto_certificate_generation_switch = LegacyWaffleSwitch( namespace, certs_waffle.AUTO_CERTIFICATE_GENERATION) with override_waffle_switch(auto_certificate_generation_switch, active=feature_enabled): yield
def waffle_switch(name): """ Return the corresponding namespaced waffle switch. WARNING: do not replicate this pattern. Instead of declaring waffle switch names as strings, you should create LegacyWaffleSwitch objects as top-level constants. """ return LegacyWaffleSwitch(waffle(), name, module_name=__name__)
def configure_waffle_namespace(feature_enabled): """ Context manager to configure the certs flags """ namespace = certs_waffle.waffle() auto_certificate_generation_switch = LegacyWaffleSwitch(namespace, certs_waffle.AUTO_CERTIFICATE_GENERATION) # pylint: disable=toggle-missing-annotation with override_waffle_switch(auto_certificate_generation_switch, active=feature_enabled): yield
def waffle_switch(name): """ Deprecated: Return the corresponding namespaced waffle switch. IMPORTANT: Do NOT copy this pattern and do NOT use this to reference new switches. Instead, replace the string constants above with the actual switch instances. For example:: ASSUME_ZERO_GRADE_IF_ABSENT = WaffleSwitch(f'{WAFFLE_NAMESPACE}.assume_zero_grade_if_absent') """ return LegacyWaffleSwitch(waffle(), name, module_name=__name__)
def override(self, switch_name, active=True): """ Deprecated method: instead, use edx_toggles.toggles.testutils.override_waffle_switch. """ warnings.warn( ("WaffleSwitchNamespace.override is deprecated. Instead, use" " edx_toggles.toggles.testutils.override_waffle_switch."), DeprecationWarning, stacklevel=2, ) set_custom_attribute("deprecated_waffle_utils", "WaffleSwitchNamespace.override") from edx_toggles.toggles.testutils import override_waffle_switch with override_waffle_switch( LegacyWaffleSwitch(self, switch_name, module_name=__name__), active): yield
""" Waffle flags and switches for user authn. """ from edx_toggles.toggles import LegacyWaffleSwitch, LegacyWaffleSwitchNamespace _WAFFLE_NAMESPACE = u'user_authn' _WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(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 = LegacyWaffleSwitch( _WAFFLE_SWITCH_NAMESPACE, 'enable_login_using_thirdparty_auth_only', __name__ )
_WAFFLE_NAMESPACE = 'user_authn' _WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(name=_WAFFLE_NAMESPACE, log_prefix='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 = LegacyWaffleSwitch( _WAFFLE_SWITCH_NAMESPACE, 'enable_login_using_thirdparty_auth_only', __name__ ) # .. toggle_name: user_authn.enable_pwned_password_api # .. toggle_implementation: WaffleSwitch # .. toggle_default: False # .. toggle_description: When enabled, user password's vulnerability would be checked via pwned password database # .. toggle_use_cases: temporary # .. toggle_creation_date: 2021-09-22 # .. toggle_target_removal_date: 2021-12-31 # .. toggle_tickets: VAN-664 ENABLE_PWNED_PASSWORD_API = LegacyWaffleSwitch( _WAFFLE_SWITCH_NAMESPACE, 'enable_pwned_password_api', __name__
from lms.djangoapps.experiments.flags import ExperimentWaffleFlag from lms.djangoapps.experiments.models import ExperimentData WAFFLE_FLAG_NAMESPACE = LegacyWaffleFlagNamespace(name='schedules') WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(name='schedules') # .. toggle_name: schedules.enable_debugging # .. toggle_implementation: WaffleFlag # .. toggle_default: False # .. toggle_description: Enable debug level of logging for schedules messages. # .. toggle_use_cases: open_edx # .. toggle_creation_date: 2017-09-17 DEBUG_MESSAGE_WAFFLE_FLAG = WaffleFlag('schedules.enable_debugging', __name__) COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH = LegacyWaffleSwitch( # lint-amnesty, pylint: disable=toggle-missing-annotation WAFFLE_SWITCH_NAMESPACE, 'course_update_show_unsubscribe', __name__) # This experiment waffle is supporting an A/B test we are running on sending course updates from an external service, # rather than through platform and ACE. See ticket AA-661 for more information. # Don't use this flag directly, instead use the `set_up_external_updates_for_enrollment` and `query_external_updates` # methods below. We save this flag decision at enrollment time and don't change it even if the flag changes. So you # can't just directly look at flag result. _EXTERNAL_COURSE_UPDATES_EXPERIMENT_ID = 18 _EXTERNAL_COURSE_UPDATES_FLAG = ExperimentWaffleFlag( WAFFLE_FLAG_NAMESPACE, 'external_updates', __name__, # lint-amnesty, pylint: disable=toggle-missing-annotation experiment_id=_EXTERNAL_COURSE_UPDATES_EXPERIMENT_ID, use_course_aware_bucketing=False)
""" 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. """ default_app_config = 'openedx.core.djangoapps.programs.apps.ProgramsConfig' from edx_toggles.toggles import LegacyWaffleSwitch, LegacyWaffleSwitchNamespace # lint-amnesty, pylint: disable=wrong-import-position PROGRAMS_WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(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 = LegacyWaffleSwitch( PROGRAMS_WAFFLE_SWITCH_NAMESPACE, 'always_calculate_program_price_as_anonymous_user', __name__)
from edx_toggles.toggles import LegacyWaffleSwitch, LegacyWaffleSwitchNamespace WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace( 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_target_removal_date: None # .. toggle_warnings: None # .. toggle_tickets: https://openedx.atlassian.net/browse/LEARNER-5527 USE_RATE_LIMIT_2_FOR_COURSE_LIST_API = LegacyWaffleSwitch( 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_target_removal_date: None # .. toggle_warnings: None # .. toggle_tickets: https://openedx.atlassian.net/browse/LEARNER-5527 USE_RATE_LIMIT_10_FOR_COURSE_LIST_API = LegacyWaffleSwitch( WAFFLE_SWITCH_NAMESPACE, 'rate_limit_10', __name__)
from lms.djangoapps.certificates.generation_handler import CERTIFICATES_USE_UPDATED from lms.djangoapps.certificates.data import CertificateStatuses from lms.djangoapps.certificates.models import ( CertificateGenerationConfiguration, GeneratedCertificate ) from lms.djangoapps.certificates.signals import _fire_ungenerated_certificate_task from lms.djangoapps.certificates.tests.factories import CertificateAllowlistFactory, GeneratedCertificateFactory from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory from lms.djangoapps.grades.tests.utils import mock_passing_grade from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from openedx.core.djangoapps.certificates.config import waffle from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory AUTO_CERTIFICATE_GENERATION_SWITCH = LegacyWaffleSwitch(waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION) # lint-amnesty, pylint: disable=toggle-missing-annotation class SelfGeneratedCertsSignalTest(ModuleStoreTestCase): """ Tests for enabling/disabling self-generated certificates according to course-pacing. """ ENABLED_SIGNALS = ['course_published'] def setUp(self): super().setUp() CertificateGenerationConfiguration.objects.create(enabled=True) def test_cert_generation_flag_on_pacing_toggle(self): """ Verify that signal enables or disables self-generated certificates
""" 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. """ default_app_config = 'openedx.core.djangoapps.programs.apps.ProgramsConfig' from edx_toggles.toggles import LegacyWaffleSwitch, LegacyWaffleSwitchNamespace # lint-amnesty, pylint: disable=wrong-import-position PROGRAMS_WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(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 = LegacyWaffleSwitch( # lint-amnesty, pylint: disable=toggle-missing-annotation PROGRAMS_WAFFLE_SWITCH_NAMESPACE, 'always_calculate_program_price_as_anonymous_user', __name__ )
""" Waffle flags and switches for third party auth . """ from edx_toggles.toggles import LegacyWaffleSwitch, LegacyWaffleSwitchNamespace _WAFFLE_NAMESPACE = u'third_party_auth' _WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace( name=_WAFFLE_NAMESPACE, log_prefix=u'ThirdPartyAuth: ') # .. toggle_name: third_party_auth.enable_multiple_sso_accounts_association_to_saml_user # .. toggle_implementation: WaffleSwitch # .. toggle_default: False # .. toggle_description: If enabled than learner should not be prompted for their edX password arriving via SAML # and already linked to the enterprise customer linked to the same IdP." # .. toggle_use_cases: temporary # .. toggle_creation_date: 2021-01-29 # .. toggle_target_removal_date: 2021-04-31 # .. toggle_warnings: None. # .. toggle_tickets: ENT-4034 ENABLE_MULTIPLE_SSO_ACCOUNTS_ASSOCIATION_TO_SAML_USER = LegacyWaffleSwitch( _WAFFLE_SWITCH_NAMESPACE, 'enable_multiple_sso_accounts_association_to_saml_user', __name__)
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory from lms.djangoapps.certificates import api as certs_api from lms.djangoapps.certificates.generation_handler import CERTIFICATES_USE_ALLOWLIST from lms.djangoapps.certificates.models import ( CertificateGenerationConfiguration, CertificateStatuses, GeneratedCertificate) from lms.djangoapps.certificates.signals import fire_ungenerated_certificate_task from lms.djangoapps.certificates.tasks import CERTIFICATE_DELAY_SECONDS from lms.djangoapps.certificates.tests.factories import CertificateWhitelistFactory from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory from lms.djangoapps.grades.tests.utils import mock_passing_grade from lms.djangoapps.verify_student.models import IDVerificationAttempt, SoftwareSecurePhotoVerification from openedx.core.djangoapps.certificates.config import waffle AUTO_CERTIFICATE_GENERATION_SWITCH = LegacyWaffleSwitch( waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION) class SelfGeneratedCertsSignalTest(ModuleStoreTestCase): """ Tests for enabling/disabling self-generated certificates according to course-pacing. """ ENABLED_SIGNALS = ['course_published'] def setUp(self): super(SelfGeneratedCertsSignalTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments CertificateGenerationConfiguration.objects.create(enabled=True) def test_cert_generation_flag_on_pacing_toggle(self): """ Verify that signal enables or disables self-generated certificates
""" Contains configuration for schedules app """ from edx_toggles.toggles import (LegacyWaffleFlag, LegacyWaffleFlagNamespace, LegacyWaffleSwitch, LegacyWaffleSwitchNamespace) from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag WAFFLE_FLAG_NAMESPACE = LegacyWaffleFlagNamespace(name='schedules') WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(name='schedules') CREATE_SCHEDULE_WAFFLE_FLAG = CourseWaffleFlag( waffle_namespace=WAFFLE_FLAG_NAMESPACE, flag_name='create_schedules_for_course', module_name=__name__, ) COURSE_UPDATE_WAFFLE_FLAG = CourseWaffleFlag( waffle_namespace=WAFFLE_FLAG_NAMESPACE, flag_name='send_updates_for_course', module_name=__name__, ) DEBUG_MESSAGE_WAFFLE_FLAG = LegacyWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'enable_debugging', __name__) COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH = LegacyWaffleSwitch( WAFFLE_SWITCH_NAMESPACE, 'course_update_show_unsubscribe', __name__)
is_using_certificate_allowlist_and_is_on_allowlist) from lms.djangoapps.certificates.models import CertificateStatuses, GeneratedCertificate from lms.djangoapps.certificates.tests.factories import ( CertificateInvalidationFactory, CertificateWhitelistFactory, GeneratedCertificateFactory) from openedx.core.djangoapps.certificates.config import waffle from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory log = logging.getLogger(__name__) ID_VERIFIED_METHOD = 'lms.djangoapps.verify_student.services.IDVerificationService.user_is_verified' AUTO_GENERATION_NAMESPACE = waffle.WAFFLE_NAMESPACE AUTO_GENERATION_NAME = waffle.AUTO_CERTIFICATE_GENERATION AUTO_GENERATION_SWITCH_NAME = f'{AUTO_GENERATION_NAMESPACE}.{AUTO_GENERATION_NAME}' AUTO_GENERATION_SWITCH = LegacyWaffleSwitch(AUTO_GENERATION_NAMESPACE, AUTO_GENERATION_NAME) @override_switch(AUTO_GENERATION_SWITCH_NAME, active=True) @override_waffle_flag(CERTIFICATES_USE_ALLOWLIST, active=True) @mock.patch(ID_VERIFIED_METHOD, mock.Mock(return_value=True)) @ddt.ddt class AllowlistTests(ModuleStoreTestCase): """ Tests for handling allowlist certificates """ def setUp(self): super().setUp() # Create user, a course run, and an enrollment self.user = UserFactory()
BulkChangeEnrollmentConfiguration, BulkUnenrollConfiguration, CourseAccessRole, CourseEnrollment, CourseEnrollmentAllowed, CourseEnrollmentCelebration, DashboardConfiguration, LinkedInAddToProfileConfiguration, LoginFailures, PendingNameChange, Registration, RegistrationCookieConfiguration, UserAttribute, UserProfile, UserTestGroup) from common.djangoapps.student.roles import REGISTERED_ACCESS_ROLES from xmodule.modulestore.django import modulestore User = get_user_model() # pylint:disable=invalid-name # This switch exists because the CourseEnrollment admin views make DB queries that impact performance. # In a large enough deployment of Open edX, this is enough to cause a site outage. # See https://openedx.atlassian.net/browse/OPS-2943 COURSE_ENROLLMENT_ADMIN_SWITCH = LegacyWaffleSwitch(STUDENT_WAFFLE_NAMESPACE, 'courseenrollment_admin', __name__) class _Check(object): """ A method decorator that pre-emptively returns false if a feature is disabled. Otherwise, it returns the return value of the decorated method. To use, add this decorator above a method and pass in a function that returns a boolean indicating whether the feature is enabled. Example: @_Check.is_enabled(FEATURE_TOGGLE.is_enabled) """ @classmethod