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
Example #2
0
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__)
Example #3
0
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__)
Example #5
0
    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
Example #6
0
"""
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__
)
Example #7
0
_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__
Example #8
0
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)

Example #9
0
"""
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__)
Example #10
0
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__)
Example #11
0
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__
)
Example #13
0
"""
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__)
Example #14
0
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
Example #15
0
"""
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__)
Example #16
0
    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()
Example #17
0
    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