From a98dd3f748dd3f57b6ce66e491075595a991f7af Mon Sep 17 00:00:00 2001 From: Taylor Payne Date: Wed, 18 Jun 2025 10:59:36 -0600 Subject: [PATCH] refactor: move explicitly shared settings into new common module --- .coveragerc | 1 + .coveragerc-local | 1 + .github/workflows/pylint-checks.yml | 2 +- cms/envs/common.py | 117 +-- lms/envs/common.py | 703 +--------------- lms/envs/devstack.py | 8 +- lms/envs/docs/README.rst | 6 +- .../user_authn/views/tests/test_register.py | 6 +- openedx/envs/__init__.py | 0 openedx/envs/common.py | 788 ++++++++++++++++++ scripts/vulture/find-dead-code.sh | 2 +- setup.cfg | 2 +- 12 files changed, 823 insertions(+), 813 deletions(-) create mode 100644 openedx/envs/__init__.py create mode 100644 openedx/envs/common.py diff --git a/.coveragerc b/.coveragerc index 3dd061ce8e..7d8fe1c269 100644 --- a/.coveragerc +++ b/.coveragerc @@ -25,6 +25,7 @@ omit = common/djangoapps/*/migrations/* openedx/core/djangoapps/*/migrations/* openedx/core/djangoapps/debug/* + openedx/envs/* openedx/features/*/migrations/* concurrency=multiprocessing diff --git a/.coveragerc-local b/.coveragerc-local index d97bf738c3..05e79fe343 100644 --- a/.coveragerc-local +++ b/.coveragerc-local @@ -24,6 +24,7 @@ omit = common/djangoapps/*/migrations/* openedx/core/djangoapps/*/migrations/* openedx/core/djangoapps/debug/* + openedx/envs/* openedx/features/*/migrations/* concurrency=multiprocessing diff --git a/.github/workflows/pylint-checks.yml b/.github/workflows/pylint-checks.yml index 6329173d4c..dd90fd05d9 100644 --- a/.github/workflows/pylint-checks.yml +++ b/.github/workflows/pylint-checks.yml @@ -20,7 +20,7 @@ jobs: - module-name: openedx-1 path: "openedx/core/types/ openedx/core/djangoapps/ace_common/ openedx/core/djangoapps/agreements/ openedx/core/djangoapps/api_admin/ openedx/core/djangoapps/auth_exchange/ openedx/core/djangoapps/bookmarks/ openedx/core/djangoapps/cache_toolbox/ openedx/core/djangoapps/catalog/ openedx/core/djangoapps/ccxcon/ openedx/core/djangoapps/commerce/ openedx/core/djangoapps/common_initialization/ openedx/core/djangoapps/common_views/ openedx/core/djangoapps/config_model_utils/ openedx/core/djangoapps/content/ openedx/core/djangoapps/content_libraries/ openedx/core/djangoapps/content_staging/ openedx/core/djangoapps/contentserver/ openedx/core/djangoapps/cookie_metadata/ openedx/core/djangoapps/cors_csrf/ openedx/core/djangoapps/course_apps/ openedx/core/djangoapps/course_date_signals/ openedx/core/djangoapps/course_groups/ openedx/core/djangoapps/courseware_api/ openedx/core/djangoapps/crawlers/ openedx/core/djangoapps/credentials/ openedx/core/djangoapps/credit/ openedx/core/djangoapps/dark_lang/ openedx/core/djangoapps/debug/ openedx/core/djangoapps/discussions/ openedx/core/djangoapps/django_comment_common/ openedx/core/djangoapps/embargo/ openedx/core/djangoapps/enrollments/ openedx/core/djangoapps/external_user_ids/ openedx/core/djangoapps/zendesk_proxy/ openedx/core/djangolib/ openedx/core/lib/ openedx/core/djangoapps/course_live/" - module-name: openedx-2 - path: "openedx/core/djangoapps/geoinfo/ openedx/core/djangoapps/header_control/ openedx/core/djangoapps/heartbeat/ openedx/core/djangoapps/lang_pref/ openedx/core/djangoapps/models/ openedx/core/djangoapps/monkey_patch/ openedx/core/djangoapps/oauth_dispatch/ openedx/core/djangoapps/olx_rest_api/ openedx/core/djangoapps/password_policy/ openedx/core/djangoapps/plugin_api/ openedx/core/djangoapps/plugins/ openedx/core/djangoapps/profile_images/ openedx/core/djangoapps/programs/ openedx/core/djangoapps/safe_sessions/ openedx/core/djangoapps/schedules/ openedx/core/djangoapps/service_status/ openedx/core/djangoapps/session_inactivity_timeout/ openedx/core/djangoapps/signals/ openedx/core/djangoapps/site_configuration/ openedx/core/djangoapps/system_wide_roles/ openedx/core/djangoapps/theming/ openedx/core/djangoapps/user_api/ openedx/core/djangoapps/user_authn/ openedx/core/djangoapps/util/ openedx/core/djangoapps/verified_track_content/ openedx/core/djangoapps/video_config/ openedx/core/djangoapps/video_pipeline/ openedx/core/djangoapps/waffle_utils/ openedx/core/djangoapps/xblock/ openedx/core/djangoapps/xmodule_django/ openedx/core/tests/ openedx/features/ openedx/testing/ openedx/tests/ openedx/core/djangoapps/notifications/ openedx/core/djangoapps/staticfiles/ openedx/core/djangoapps/content_tagging/" + path: "openedx/core/djangoapps/geoinfo/ openedx/core/djangoapps/header_control/ openedx/core/djangoapps/heartbeat/ openedx/core/djangoapps/lang_pref/ openedx/core/djangoapps/models/ openedx/core/djangoapps/monkey_patch/ openedx/core/djangoapps/oauth_dispatch/ openedx/core/djangoapps/olx_rest_api/ openedx/core/djangoapps/password_policy/ openedx/core/djangoapps/plugin_api/ openedx/core/djangoapps/plugins/ openedx/core/djangoapps/profile_images/ openedx/core/djangoapps/programs/ openedx/core/djangoapps/safe_sessions/ openedx/core/djangoapps/schedules/ openedx/core/djangoapps/service_status/ openedx/core/djangoapps/session_inactivity_timeout/ openedx/core/djangoapps/signals/ openedx/core/djangoapps/site_configuration/ openedx/core/djangoapps/system_wide_roles/ openedx/core/djangoapps/theming/ openedx/core/djangoapps/user_api/ openedx/core/djangoapps/user_authn/ openedx/core/djangoapps/util/ openedx/core/djangoapps/verified_track_content/ openedx/core/djangoapps/video_config/ openedx/core/djangoapps/video_pipeline/ openedx/core/djangoapps/waffle_utils/ openedx/core/djangoapps/xblock/ openedx/core/djangoapps/xmodule_django/ openedx/core/tests/ openedx/features/ openedx/testing/ openedx/tests/ openedx/envs/ openedx/core/djangoapps/notifications/ openedx/core/djangoapps/staticfiles/ openedx/core/djangoapps/content_tagging/" - module-name: common path: "common" - module-name: cms diff --git a/cms/envs/common.py b/cms/envs/common.py index 55861eed44..9931779221 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -45,87 +45,21 @@ import sys from corsheaders.defaults import default_headers as corsheaders_default_headers from datetime import timedelta + +from django.utils.translation import gettext_lazy as _ + import lms.envs.common -# Although this module itself may not use these imported variables, other dependent modules may. -# Warning: Do NOT add any new variables to this list. This is incompatible with future plans to -# have more logical separation between LMS and Studio (CMS). It is also incompatible with the -# direction documented in OEP-45: Configuring and Operating Open edX: -# https://open-edx-proposals.readthedocs.io/en/latest/oep-0045-arch-ops-and-config.html + +from openedx.core.constants import COURSE_KEY_REGEX, COURSE_KEY_PATTERN, COURSE_ID_PATTERN +from openedx.envs.common import * # pylint: disable=wildcard-import + from lms.envs.common import ( - USE_TZ, ALL_LANGUAGES, ASSET_IGNORE_REGEX, - PARENTAL_CONSENT_AGE_LIMIT, REGISTRATION_EMAIL_PATTERNS_ALLOWED, - # The following PROFILE_IMAGE_* settings are included as they are - # indirectly accessed through the email opt-in API, which is - # technically accessible through the CMS via legacy URLs. - PROFILE_IMAGE_BACKEND, PROFILE_IMAGE_DEFAULT_FILENAME, PROFILE_IMAGE_DEFAULT_FILE_EXTENSION, - PROFILE_IMAGE_HASH_SEED, PROFILE_IMAGE_MIN_BYTES, PROFILE_IMAGE_MAX_BYTES, PROFILE_IMAGE_SIZES_MAP, - # The following setting is included as it is used to check whether to - # display credit eligibility table on the CMS or not. - COURSE_MODE_DEFAULTS, DEFAULT_COURSE_ABOUT_IMAGE_URL, + # NOTE: Do not add any new imports here. Use openedx.envs.common instead for + # platform wide settings. - # User-uploaded content - MEDIA_ROOT, - MEDIA_URL, - - # Lazy Gettext - _, - - # Django REST framework configuration - REST_FRAMEWORK, - - STATICI18N_OUTPUT_DIR, - - # Heartbeat - HEARTBEAT_CHECKS, - HEARTBEAT_EXTENDED_CHECKS, - HEARTBEAT_CELERY_TIMEOUT, - HEARTBEAT_CELERY_ROUTING_KEY, - - # Default site to use if no site exists matching request headers - SITE_ID, - - # constants for redirects app - REDIRECT_CACHE_TIMEOUT, - REDIRECT_CACHE_KEY_PREFIX, - - # This is required for the migrations in oauth_dispatch.models - # otherwise it fails saying this attribute is not present in Settings - # Although Studio does not enable OAuth2 Provider capability, the new approach - # to generating test databases will discover and try to create all tables - # and this setting needs to be present - OAUTH2_PROVIDER_APPLICATION_MODEL, - JWT_AUTH, - - USERNAME_REGEX_PARTIAL, - USERNAME_PATTERN, - - # django-debug-toolbar - DEBUG_TOOLBAR_PATCH_SETTINGS, - - COURSE_ENROLLMENT_MODES, - CONTENT_TYPE_GATE_GROUP_IDS, - - DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH, - - GENERATE_PROFILE_SCORES, - - # Enterprise service settings - ENTERPRISE_CATALOG_INTERNAL_ROOT_URL, - ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_KEY, - ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_SECRET, - ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_PROVIDER_URL, - - # Methods to derive settings - _make_mako_template_dirs, - _make_locale_paths, - - # Password Validator Settings - AUTH_PASSWORD_VALIDATORS -) -from lms.envs.common import ( # FIXME: The HIBP settings are only used in the LMS, but CMS unit tests fail # without them. Perhaps moving some code would allow us to remove these from - # this file. + # this file. GitHub Issue: https://github.com/openedx/edx-platform/issues/36992. ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY, ENABLE_AUTHN_LOGIN_NUDGE_HIBP_POLICY, ENABLE_AUTHN_REGISTER_HIBP_POLICY, @@ -133,15 +67,6 @@ from lms.envs.common import ( HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD, HIBP_LOGIN_NUDGE_PASSWORD_FREQUENCY_THRESHOLD, HIBP_REGISTRATION_PASSWORD_FREQUENCY_THRESHOLD, - - USE_EXTRACTED_WORD_CLOUD_BLOCK, - USE_EXTRACTED_ANNOTATABLE_BLOCK, - USE_EXTRACTED_POLL_QUESTION_BLOCK, - USE_EXTRACTED_LTI_BLOCK, - USE_EXTRACTED_HTML_BLOCK, - USE_EXTRACTED_DISCUSSION_BLOCK, - USE_EXTRACTED_PROBLEM_BLOCK, - USE_EXTRACTED_VIDEO_BLOCK, ) from path import Path as path from django.urls import reverse_lazy @@ -700,7 +625,7 @@ TEMPLATES = [ # Don't look for template source files inside installed applications. 'APP_DIRS': False, # Instead, look for template source files in these dirs. - 'DIRS': Derived(_make_mako_template_dirs), + 'DIRS': Derived(make_mako_template_dirs), # Options specific to this backend. 'OPTIONS': { 'loaders': ( @@ -719,7 +644,7 @@ TEMPLATES = [ 'NAME': 'mako', 'BACKEND': 'common.djangoapps.edxmako.backend.Mako', 'APP_DIRS': False, - 'DIRS': Derived(_make_mako_template_dirs), + 'DIRS': Derived(make_mako_template_dirs), 'OPTIONS': { 'context_processors': CONTEXT_PROCESSORS, 'debug': False, @@ -823,12 +748,6 @@ ELASTIC_SEARCH_CONFIG = [ } ] -# These are standard regexes for pulling out info like course_ids, usage_ids, etc. -# They are used so that URLs with deprecated-format strings still work. -from lms.envs.common import ( - COURSE_KEY_PATTERN, COURSE_KEY_REGEX, COURSE_ID_PATTERN, USAGE_KEY_PATTERN, ASSET_KEY_PATTERN -) - ######################### CSRF ######################################### # Forwards-compatibility with Django 1.7 @@ -1254,12 +1173,6 @@ STATICFILES_DIRS = [ CELERY_TIMEZONE = 'UTC' TIME_ZONE = 'UTC' LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGES_BIDI = lms.envs.common.LANGUAGES_BIDI - -LANGUAGE_COOKIE_NAME = lms.envs.common.LANGUAGE_COOKIE_NAME - -LANGUAGES = lms.envs.common.LANGUAGES -LANGUAGE_DICT = dict(LANGUAGES) # Languages supported for custom course certificate templates CERTIFICATE_TEMPLATE_LANGUAGES = { @@ -1273,8 +1186,6 @@ USE_L10N = True STATICI18N_FILENAME_FUNCTION = 'statici18n.utils.legacy_filename' STATICI18N_ROOT = PROJECT_ROOT / "static" -LOCALE_PATHS = Derived(_make_locale_paths) - # Messages MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' @@ -1540,6 +1451,10 @@ CELERY_BROKER_VHOST = '' CELERY_BROKER_USE_SSL = False CELERY_EVENT_QUEUE_TTL = None +############################## HEARTBEAT ###################################### + +HEARTBEAT_CELERY_ROUTING_KEY = HIGH_PRIORITY_QUEUE + ############################## Video ########################################## YOUTUBE = { diff --git a/lms/envs/common.py b/lms/envs/common.py index e0f106ee80..eac73997e6 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -65,12 +65,10 @@ from enterprise.constants import ( ) from openedx.core.constants import COURSE_KEY_REGEX, COURSE_KEY_PATTERN, COURSE_ID_PATTERN -from openedx.core.djangoapps.theming.helpers_dirs import ( - get_themes_unchecked, - get_theme_base_dirs_from_settings -) from openedx.core.lib.derived import Derived from openedx.core.release import doc_version +from openedx.envs.common import * # pylint: disable=wildcard-import + from lms.djangoapps.lms_xblock.mixin import LmsBlockMixin ################################### FEATURES ################################### @@ -1083,15 +1081,9 @@ FEATURES = { # e.g. COURSE_BLOCKS_API_EXTRA_FIELDS = [ ('course', 'other_course_settings'), ("problem", "weight") ] COURSE_BLOCKS_API_EXTRA_FIELDS = [] - -ASSET_IGNORE_REGEX = r"(^\._.*$)|(^\.DS_Store$)|(^.*~$)" - # Used for A/B testing DEFAULT_GROUPS = [] -# If this is true, random scores will be generated for the purpose of debugging the profile graphs -GENERATE_PROFILE_SCORES = False - # .. setting_name: GRADEBOOK_FREEZE_DAYS # .. setting_default: 30 # .. setting_description: Sets the number of days after which the gradebook will freeze following the course's end. @@ -1282,9 +1274,6 @@ OAUTH2_PROVIDER = { 'REQUEST_APPROVAL_PROMPT': 'auto_even_if_expired', 'ERROR_RESPONSE_WITH_SCOPES': True, } -# This is required for the migrations in oauth_dispatch.models -# otherwise it fails saying this attribute is not present in Settings -OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application' # Automatically clean up edx-django-oauth2-provider tokens on use OAUTH_DELETE_EXPIRED = True @@ -1324,19 +1313,6 @@ MAKO_TEMPLATE_DIRS_BASE = [ OPENEDX_ROOT / 'features' / 'course_experience' / 'templates', ] - -def _make_mako_template_dirs(settings): - """ - Derives the final Mako template directories list from other settings. - """ - if settings.ENABLE_COMPREHENSIVE_THEMING: - themes_dirs = get_theme_base_dirs_from_settings(settings.COMPREHENSIVE_THEME_DIRS) - for theme in get_themes_unchecked(themes_dirs, settings.PROJECT_ROOT): - if theme.themes_base_dir not in settings.MAKO_TEMPLATE_DIRS_BASE: - settings.MAKO_TEMPLATE_DIRS_BASE.insert(0, theme.themes_base_dir) - return settings.MAKO_TEMPLATE_DIRS_BASE - - CONTEXT_PROCESSORS = [ 'django.template.context_processors.request', 'django.template.context_processors.static', @@ -1364,9 +1340,7 @@ CONTEXT_PROCESSORS = [ 'lms.djangoapps.mobile_api.context_processor.is_from_mobile_app', # Context processor necessary for the survey report message appear on the admin site - 'openedx.features.survey_report.context_processors.admin_extra_context' - - + 'openedx.features.survey_report.context_processors.admin_extra_context', ] # Django templating @@ -1404,7 +1378,7 @@ TEMPLATES = [ # Don't look for template source files inside installed applications. 'APP_DIRS': False, # Instead, look for template source files in these dirs. - 'DIRS': Derived(_make_mako_template_dirs), + 'DIRS': Derived(make_mako_template_dirs), # Options specific to this backend. 'OPTIONS': { 'context_processors': CONTEXT_PROCESSORS, @@ -1514,36 +1488,10 @@ WIKI_ENABLED = True ### -COURSE_MODE_DEFAULTS = { - 'android_sku': None, - 'bulk_sku': None, - 'currency': 'usd', - 'description': None, - 'expiration_datetime': None, - 'ios_sku': None, - 'min_price': 0, - 'name': _('Audit'), - 'sku': None, - 'slug': 'audit', - 'suggested_prices': '', -} - # IP addresses that are allowed to reload the course, etc. # TODO (vshnayder): Will probably need to change as we get real access control in. LMS_MIGRATION_ALLOWED_IPS = [] -USAGE_KEY_PATTERN = r'(?P(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))' -ASSET_KEY_PATTERN = r'(?P(?:/?c4x(:/)?/[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))' -USAGE_ID_PATTERN = r'(?P(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))' - - -# The space is required for space-dependent languages like Arabic and Farsi. -# However, backward compatibility with Ficus older releases is still maintained (space is still not valid) -# in the AccountCreationForm and the user_api through the ENABLE_UNICODE_USERNAME feature flag. -USERNAME_REGEX_PARTIAL = r'[\w .@_+-]+' -USERNAME_PATTERN = fr'(?P{USERNAME_REGEX_PARTIAL})' - - ############################## EVENT TRACKING ################################# LMS_SEGMENT_KEY = None @@ -1862,7 +1810,6 @@ CODE_JAIL_REST_SERVICE_READ_TIMEOUT = 3.5 # time in seconds ############################### DJANGO BUILT-INS ############################### # Change DEBUG in your environment settings files, not here DEBUG = False -USE_TZ = True SESSION_COOKIE_SECURE = False SESSION_SAVE_EVERY_REQUEST = False SESSION_SERIALIZER = 'openedx.core.lib.session_serializers.PickleSerializer' @@ -1937,106 +1884,11 @@ STATICFILES_DIRS = [ ] FAVICON_PATH = 'images/favicon.ico' -DEFAULT_COURSE_ABOUT_IMAGE_URL = 'images/pencils.jpg' - -# User-uploaded content -MEDIA_ROOT = '/edx/var/edxapp/media/' -MEDIA_URL = '/media/' # Locale/Internationalization CELERY_TIMEZONE = 'UTC' TIME_ZONE = 'UTC' LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html -# these languages display right to left -LANGUAGES_BIDI = ("he", "ar", "fa", "ur", "fa-ir", "rtl") - -LANGUAGE_COOKIE_NAME = "openedx-language-preference" - -# Sourced from http://www.localeplanet.com/icu/ and wikipedia -LANGUAGES = [ - ('en', 'English'), - ('rtl', 'Right-to-Left Test Language'), - ('eo', 'Dummy Language (Esperanto)'), # Dummy languaged used for testing - - ('am', 'አማርኛ'), # Amharic - ('ar', 'العربية'), # Arabic - ('az', 'azərbaycanca'), # Azerbaijani - ('bg-bg', 'български (България)'), # Bulgarian (Bulgaria) - ('bn-bd', 'বাংলা (বাংলাদেশ)'), # Bengali (Bangladesh) - ('bn-in', 'বাংলা (ভারত)'), # Bengali (India) - ('bs', 'bosanski'), # Bosnian - ('ca', 'Català'), # Catalan - ('ca@valencia', 'Català (València)'), # Catalan (Valencia) - ('cs', 'Čeština'), # Czech - ('cy', 'Cymraeg'), # Welsh - ('da', 'dansk'), # Danish - ('de-de', 'Deutsch (Deutschland)'), # German (Germany) - ('el', 'Ελληνικά'), # Greek - ('en-uk', 'English (United Kingdom)'), # English (United Kingdom) - ('en@lolcat', 'LOLCAT English'), # LOLCAT English - ('en@pirate', 'Pirate English'), # Pirate English - ('es-419', 'Español (Latinoamérica)'), # Spanish (Latin America) - ('es-ar', 'Español (Argentina)'), # Spanish (Argentina) - ('es-ec', 'Español (Ecuador)'), # Spanish (Ecuador) - ('es-es', 'Español (España)'), # Spanish (Spain) - ('es-mx', 'Español (México)'), # Spanish (Mexico) - ('es-pe', 'Español (Perú)'), # Spanish (Peru) - ('et-ee', 'Eesti (Eesti)'), # Estonian (Estonia) - ('eu-es', 'euskara (Espainia)'), # Basque (Spain) - ('fa', 'فارسی'), # Persian - ('fa-ir', 'فارسی (ایران)'), # Persian (Iran) - ('fi-fi', 'Suomi (Suomi)'), # Finnish (Finland) - ('fil', 'Filipino'), # Filipino - ('fr', 'Français'), # French - ('gl', 'Galego'), # Galician - ('gu', 'ગુજરાતી'), # Gujarati - ('he', 'עברית'), # Hebrew - ('hi', 'हिन्दी'), # Hindi - ('hr', 'hrvatski'), # Croatian - ('hu', 'magyar'), # Hungarian - ('hy-am', 'Հայերեն (Հայաստան)'), # Armenian (Armenia) - ('id', 'Bahasa Indonesia'), # Indonesian - ('it-it', 'Italiano (Italia)'), # Italian (Italy) - ('ja-jp', '日本語 (日本)'), # Japanese (Japan) - ('kk-kz', 'қазақ тілі (Қазақстан)'), # Kazakh (Kazakhstan) - ('km-kh', 'ភាសាខ្មែរ (កម្ពុជា)'), # Khmer (Cambodia) - ('kn', 'ಕನ್ನಡ'), # Kannada - ('ko-kr', '한국어 (대한민국)'), # Korean (Korea) - ('lt-lt', 'Lietuvių (Lietuva)'), # Lithuanian (Lithuania) - ('ml', 'മലയാളം'), # Malayalam - ('mn', 'Монгол хэл'), # Mongolian - ('mr', 'मराठी'), # Marathi - ('ms', 'Bahasa Melayu'), # Malay - ('nb', 'Norsk bokmål'), # Norwegian Bokmål - ('ne', 'नेपाली'), # Nepali - ('nl-nl', 'Nederlands (Nederland)'), # Dutch (Netherlands) - ('or', 'ଓଡ଼ିଆ'), # Oriya - ('pl', 'Polski'), # Polish - ('pt-br', 'Português (Brasil)'), # Portuguese (Brazil) - ('pt-pt', 'Português (Portugal)'), # Portuguese (Portugal) - ('ro', 'română'), # Romanian - ('ru', 'Русский'), # Russian - ('si', 'සිංහල'), # Sinhala - ('sk', 'Slovenčina'), # Slovak - ('sl', 'Slovenščina'), # Slovenian - ('sq', 'shqip'), # Albanian - ('sr', 'Српски'), # Serbian - ('sv', 'svenska'), # Swedish - ('sw', 'Kiswahili'), # Swahili - ('ta', 'தமிழ்'), # Tamil - ('te', 'తెలుగు'), # Telugu - ('th', 'ไทย'), # Thai - ('tr-tr', 'Türkçe (Türkiye)'), # Turkish (Turkey) - ('uk', 'Українська'), # Ukranian - ('ur', 'اردو'), # Urdu - ('vi', 'Tiếng Việt'), # Vietnamese - ('uz', 'Ўзбек'), # Uzbek - ('zh-cn', '中文 (简体)'), # Chinese (China) - ('zh-hk', '中文 (香港)'), # Chinese (Hong Kong) - ('zh-tw', '中文 (台灣)'), # Chinese (Taiwan) -] - -LANGUAGE_DICT = dict(LANGUAGES) # Languages supported for custom course certificate templates CERTIFICATE_TEMPLATE_LANGUAGES = { @@ -2049,20 +1901,6 @@ USE_L10N = True STATICI18N_FILENAME_FUNCTION = 'statici18n.utils.legacy_filename' STATICI18N_ROOT = PROJECT_ROOT / "static" -STATICI18N_OUTPUT_DIR = "js/i18n" - - -# Localization strings (e.g. django.po) are under these directories -def _make_locale_paths(settings): # pylint: disable=missing-function-docstring - locale_paths = list(settings.PREPEND_LOCALE_PATHS) - locale_paths += [settings.REPO_ROOT + '/conf/locale'] # edx-platform/conf/locale/ - - if settings.ENABLE_COMPREHENSIVE_THEMING: - # Add locale paths to settings for comprehensive theming. - for locale_path in settings.COMPREHENSIVE_THEME_LOCALE_PATHS: - locale_paths += (path(locale_path), ) - return locale_paths -LOCALE_PATHS = Derived(_make_locale_paths) # Messages MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' @@ -2191,12 +2029,6 @@ EDXNOTES_CONNECT_TIMEOUT = 0.5 # time in seconds # edx_notes_api service internal endpoint. EDXNOTES_READ_TIMEOUT = 1.5 # time in seconds -########################## Parental controls config ####################### - -# The age at which a learner no longer requires parental consent, or None -# if parental consent is never required. -PARENTAL_CONSENT_AGE_LIMIT = 13 - ######################### Branded Footer ################################### # Constants for the footer used on the site and shared with other sites # (such as marketing and the blog) via the branding API. @@ -2816,14 +2648,6 @@ WEBPACK_LOADER = { } } -########################## DJANGO DEBUG TOOLBAR ############################### - -# We don't enable Django Debug Toolbar universally, but whenever we do, we want -# to avoid patching settings. Patched settings can cause circular import -# problems: https://django-debug-toolbar.readthedocs.org/en/1.0/installation.html#explicit-setup - -DEBUG_TOOLBAR_PATCH_SETTINGS = False - ################################# CELERY ###################################### CELERY_IMPORTS = [ @@ -2913,18 +2737,6 @@ CELERY_BROKER_PASSWORD = 'celery' ############################## HEARTBEAT ###################################### -# Checks run in normal mode by the heartbeat djangoapp -HEARTBEAT_CHECKS = [ - 'openedx.core.djangoapps.heartbeat.default_checks.check_modulestore', - 'openedx.core.djangoapps.heartbeat.default_checks.check_database', -] - -# Other checks to run by default in "extended"/heavy mode -HEARTBEAT_EXTENDED_CHECKS = ( - 'openedx.core.djangoapps.heartbeat.default_checks.check_celery', -) - -HEARTBEAT_CELERY_TIMEOUT = 5 HEARTBEAT_CELERY_ROUTING_KEY = HIGH_PRIORITY_QUEUE ################################ Block Structures ################################### @@ -3417,34 +3229,6 @@ CROSS_DOMAIN_CSRF_COOKIE_DOMAIN = '' ######################### Django Rest Framework ######################## -REST_FRAMEWORK = { - # These default classes add observability around endpoints using defaults, and should - # not be used anywhere else. - # Notes on Order: - # 1. `JwtAuthentication` does not check `is_active`, so email validation does not affect it. However, - # `SessionAuthentication` does. These work differently, and order changes in what way, which really stinks. See - # https://github.com/openedx/public-engineering/issues/165 for details. - # 2. `JwtAuthentication` may also update the database based on contents. Since the LMS creates these JWTs, this - # shouldn't have any affect at this time. But it could, when and if another service started creating the JWTs. - 'DEFAULT_AUTHENTICATION_CLASSES': [ - 'openedx.core.djangolib.default_auth_classes.DefaultJwtAuthentication', - 'openedx.core.djangolib.default_auth_classes.DefaultSessionAuthentication', - ], - 'DEFAULT_PAGINATION_CLASS': 'edx_rest_framework_extensions.paginators.DefaultPagination', - 'DEFAULT_RENDERER_CLASSES': ( - 'rest_framework.renderers.JSONRenderer', - ), - 'EXCEPTION_HANDLER': 'openedx.core.lib.request_utils.ignored_error_exception_handler', - 'PAGE_SIZE': 10, - 'URL_FORMAT_OVERRIDE': None, - 'DEFAULT_THROTTLE_RATES': { - 'user': '60/minute', - 'service_user': '800/minute', - 'registration_validation': '30/minute', - 'high_service_user': '2000/minute', - }, -} - # .. setting_name: REGISTRATION_VALIDATION_RATELIMIT # .. setting_default: 30/7d # .. setting_description: Whenever a user tries to register on edx, the data entered during registration @@ -3664,7 +3448,6 @@ VERIFICATION_EXPIRY_EMAIL = { "DEFAULT_EMAILS": 2, } -DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH = "verify_student_disable_account_activation_requirement" ################ Enable credit eligibility feature #################### ENABLE_CREDIT_ELIGIBILITY = True @@ -3757,10 +3540,6 @@ REGISTRATION_FIELD_ORDER = [ "terms_of_service", ] -# Optional setting to restrict registration / account creation to only emails -# that match a regex in this list. Set to None to allow any email (default). -REGISTRATION_EMAIL_PATTERNS_ALLOWED = None - # String length for the configurable part of the auto-generated username AUTO_GENERATED_USERNAME_RANDOM_STRING_LENGTH = 4 @@ -3802,24 +3581,6 @@ FINANCIAL_REPORTS = { POLICY_CHANGE_TASK_RATE_LIMIT = '900/h' #### PASSWORD POLICY SETTINGS ##### -AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", - }, - { - "NAME": "common.djangoapps.util.password_policy_validators.MinimumLengthValidator", - "OPTIONS": { - "min_length": 8 - } - }, - { - "NAME": "common.djangoapps.util.password_policy_validators.MaximumLengthValidator", - "OPTIONS": { - "max_length": 75 - } - }, -] - PASSWORD_POLICY_COMPLIANCE_ROLLOUT_CONFIG = { 'ENFORCE_COMPLIANCE_ON_LOGIN': False } @@ -3900,200 +3661,6 @@ VIDEO_TRANSCRIPTS_SETTINGS = dict( VIDEO_TRANSCRIPTS_MAX_AGE = 31536000 -# Source: -# http://loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt according to http://en.wikipedia.org/wiki/ISO_639-1 -# Note that this is used as the set of choices to the `code` field of the -# `LanguageProficiency` model. -ALL_LANGUAGES = [ - ["aa", "Afar"], - ["ab", "Abkhazian"], - ["af", "Afrikaans"], - ["ak", "Akan"], - ["sq", "Albanian"], - ["am", "Amharic"], - ["ar", "Arabic"], - ["an", "Aragonese"], - ["hy", "Armenian"], - ["as", "Assamese"], - ["av", "Avaric"], - ["ae", "Avestan"], - ["ay", "Aymara"], - ["az", "Azerbaijani"], - ["ba", "Bashkir"], - ["bm", "Bambara"], - ["eu", "Basque"], - ["be", "Belarusian"], - ["bn", "Bengali"], - ["bh", "Bihari languages"], - ["bi", "Bislama"], - ["bs", "Bosnian"], - ["br", "Breton"], - ["bg", "Bulgarian"], - ["my", "Burmese"], - ["ca", "Catalan"], - ["ch", "Chamorro"], - ["ce", "Chechen"], - ["zh", "Chinese"], - ["zh_HANS", "Simplified Chinese"], - ["zh_HANT", "Traditional Chinese"], - ["cu", "Church Slavic"], - ["cv", "Chuvash"], - ["kw", "Cornish"], - ["co", "Corsican"], - ["cr", "Cree"], - ["cs", "Czech"], - ["da", "Danish"], - ["dv", "Divehi"], - ["nl", "Dutch"], - ["dz", "Dzongkha"], - ["en", "English"], - ["eo", "Esperanto"], - ["et", "Estonian"], - ["ee", "Ewe"], - ["fo", "Faroese"], - ["fj", "Fijian"], - ["fi", "Finnish"], - ["fr", "French"], - ["fy", "Western Frisian"], - ["ff", "Fulah"], - ["ka", "Georgian"], - ["de", "German"], - ["gd", "Gaelic"], - ["ga", "Irish"], - ["gl", "Galician"], - ["gv", "Manx"], - ["el", "Greek"], - ["gn", "Guarani"], - ["gu", "Gujarati"], - ["ht", "Haitian"], - ["ha", "Hausa"], - ["he", "Hebrew"], - ["hz", "Herero"], - ["hi", "Hindi"], - ["ho", "Hiri Motu"], - ["hr", "Croatian"], - ["hu", "Hungarian"], - ["ig", "Igbo"], - ["is", "Icelandic"], - ["io", "Ido"], - ["ii", "Sichuan Yi"], - ["iu", "Inuktitut"], - ["ie", "Interlingue"], - ["ia", "Interlingua"], - ["id", "Indonesian"], - ["ik", "Inupiaq"], - ["it", "Italian"], - ["jv", "Javanese"], - ["ja", "Japanese"], - ["kl", "Kalaallisut"], - ["kn", "Kannada"], - ["ks", "Kashmiri"], - ["kr", "Kanuri"], - ["kk", "Kazakh"], - ["km", "Central Khmer"], - ["ki", "Kikuyu"], - ["rw", "Kinyarwanda"], - ["ky", "Kirghiz"], - ["kv", "Komi"], - ["kg", "Kongo"], - ["ko", "Korean"], - ["kj", "Kuanyama"], - ["ku", "Kurdish"], - ["lo", "Lao"], - ["la", "Latin"], - ["lv", "Latvian"], - ["li", "Limburgan"], - ["ln", "Lingala"], - ["lt", "Lithuanian"], - ["lb", "Luxembourgish"], - ["lu", "Luba-Katanga"], - ["lg", "Ganda"], - ["mk", "Macedonian"], - ["mh", "Marshallese"], - ["ml", "Malayalam"], - ["mi", "Maori"], - ["mr", "Marathi"], - ["ms", "Malay"], - ["mg", "Malagasy"], - ["mt", "Maltese"], - ["mn", "Mongolian"], - ["na", "Nauru"], - ["nv", "Navajo"], - ["nr", "Ndebele, South"], - ["nd", "Ndebele, North"], - ["ng", "Ndonga"], - ["ne", "Nepali"], - ["nn", "Norwegian Nynorsk"], - ["nb", "Bokmål, Norwegian"], - ["no", "Norwegian"], - ["ny", "Chichewa"], - ["oc", "Occitan"], - ["oj", "Ojibwa"], - ["or", "Oriya"], - ["om", "Oromo"], - ["os", "Ossetian"], - ["pa", "Panjabi"], - ["fa", "Persian"], - ["pi", "Pali"], - ["pl", "Polish"], - ["pt", "Portuguese"], - ["ps", "Pushto"], - ["qu", "Quechua"], - ["rm", "Romansh"], - ["ro", "Romanian"], - ["rn", "Rundi"], - ["ru", "Russian"], - ["sg", "Sango"], - ["sa", "Sanskrit"], - ["si", "Sinhala"], - ["sk", "Slovak"], - ["sl", "Slovenian"], - ["se", "Northern Sami"], - ["sm", "Samoan"], - ["sn", "Shona"], - ["sd", "Sindhi"], - ["so", "Somali"], - ["st", "Sotho, Southern"], - ["es", "Spanish"], - ["sc", "Sardinian"], - ["sr", "Serbian"], - ["ss", "Swati"], - ["su", "Sundanese"], - ["sw", "Swahili"], - ["sv", "Swedish"], - ["ty", "Tahitian"], - ["ta", "Tamil"], - ["tt", "Tatar"], - ["te", "Telugu"], - ["tg", "Tajik"], - ["tl", "Tagalog"], - ["th", "Thai"], - ["bo", "Tibetan"], - ["ti", "Tigrinya"], - ["to", "Tonga (Tonga Islands)"], - ["tn", "Tswana"], - ["ts", "Tsonga"], - ["tk", "Turkmen"], - ["tr", "Turkish"], - ["tw", "Twi"], - ["ug", "Uighur"], - ["uk", "Ukrainian"], - ["ur", "Urdu"], - ["uz", "Uzbek"], - ["ve", "Venda"], - ["vi", "Vietnamese"], - ["vo", "Volapük"], - ["cy", "Welsh"], - ["wa", "Walloon"], - ["wo", "Wolof"], - ["xh", "Xhosa"], - ["yi", "Yiddish"], - ["yo", "Yoruba"], - ["za", "Zhuang"], - ["zu", "Zulu"] -] - - ### Apps only installed in some instances # The order of INSTALLED_APPS matters, so this tuple is the app name and the item in INSTALLED_APPS # that this app should be inserted *before*. A None here means it should be appended to the list. @@ -4390,35 +3957,6 @@ FIELD_OVERRIDE_PROVIDERS = () MODULESTORE_FIELD_OVERRIDE_PROVIDERS = ('openedx.features.content_type_gating.' 'field_override.ContentTypeGatingFieldOverride',) -# PROFILE IMAGE CONFIG -# WARNING: Certain django storage backends do not support atomic -# file overwrites (including the default, OverwriteStorage) - instead -# there are separate calls to delete and then write a new file in the -# storage backend. This introduces the risk of a race condition -# occurring when a user uploads a new profile image to replace an -# earlier one (the file will temporarily be deleted). -PROFILE_IMAGE_BACKEND = { - 'class': 'openedx.core.storage.OverwriteStorage', - 'options': { - 'location': os.path.join(MEDIA_ROOT, 'profile-images/'), - 'base_url': os.path.join(MEDIA_URL, 'profile-images/'), - }, -} -PROFILE_IMAGE_DEFAULT_FILENAME = 'images/profiles/default' -PROFILE_IMAGE_DEFAULT_FILE_EXTENSION = 'png' -# This key is used in generating unguessable URLs to users' -# profile images. Once it has been set, changing it will make the -# platform unaware of current image URLs. -PROFILE_IMAGE_HASH_SEED = 'placeholder_secret_key' -PROFILE_IMAGE_MAX_BYTES = 1024 * 1024 -PROFILE_IMAGE_MIN_BYTES = 100 -PROFILE_IMAGE_SIZES_MAP = { - 'full': 500, - 'large': 120, - 'medium': 50, - 'small': 30 -} - # Sets the maximum number of courses listed on the homepage # If set to None, all courses will be listed on the homepage HOMEPAGE_COURSE_MAX = None @@ -4444,9 +3982,6 @@ CREDIT_TASK_DEFAULT_RETRY_DELAY = 30 # to throttling. CREDIT_TASK_MAX_RETRIES = 5 -# Dummy secret key for dev/test -SECRET_KEY = 'dev key' - # Secret keys shared with credit providers. # Used to digitally sign credit requests (us --> provider) # and validate responses (provider --> us). @@ -4496,45 +4031,6 @@ DEFAULT_JWT_ISSUER = { JWT_EXPIRATION = 30 JWT_PRIVATE_SIGNING_KEY = None -JWT_AUTH = { - 'JWT_VERIFY_EXPIRATION': True, - - 'JWT_PAYLOAD_GET_USERNAME_HANDLER': lambda d: d.get('username'), - 'JWT_LEEWAY': 1, - 'JWT_DECODE_HANDLER': 'edx_rest_framework_extensions.auth.jwt.decoder.jwt_decode_handler', - - 'JWT_AUTH_COOKIE': 'edx-jwt-cookie', - - # Number of seconds before JWTs expire - 'JWT_EXPIRATION': 30, - 'JWT_IN_COOKIE_EXPIRATION': 60 * 60, - - 'JWT_LOGIN_CLIENT_ID': 'login-service-client-id', - 'JWT_LOGIN_SERVICE_USERNAME': 'login_service_user', - - 'JWT_SUPPORTED_VERSION': '1.2.0', - - 'JWT_ALGORITHM': 'HS256', - 'JWT_SECRET_KEY': SECRET_KEY, - - 'JWT_SIGNING_ALGORITHM': 'RS512', - 'JWT_PRIVATE_SIGNING_JWK': None, - 'JWT_PUBLIC_SIGNING_JWK_SET': None, - - 'JWT_ISSUER': 'http://127.0.0.1:8000/oauth2', - 'JWT_AUDIENCE': 'change-me', - 'JWT_ISSUERS': [ - { - 'ISSUER': 'http://127.0.0.1:8000/oauth2', - 'AUDIENCE': 'change-me', - 'SECRET_KEY': SECRET_KEY - } - ], - 'JWT_AUTH_COOKIE_HEADER_PAYLOAD': 'edx-jwt-cookie-header-payload', - 'JWT_AUTH_COOKIE_SIGNATURE': 'edx-jwt-cookie-signature', - 'JWT_AUTH_HEADER_PREFIX': 'JWT', -} - EDX_DRF_EXTENSIONS = { # Set this value to an empty dict in order to prevent automatically updating # user data from values in (possibly stale) JWTs. @@ -4600,12 +4096,6 @@ CREDENTIALS_COURSE_COMPLETION_STATE = 'awarded' # Queue to use for award program certificates PROGRAM_CERTIFICATES_ROUTING_KEY = 'edx.lms.core.default' -# Settings for Comprehensive Theming app - -# See https://github.com/openedx/edx-django-sites-extensions for more info -# Default site to use if site matching request headers does not exist -SITE_ID = 1 - # .. setting_name: COMPREHENSIVE_THEME_DIRS # .. setting_default: [] # .. setting_description: A list of paths to directories, each of which will @@ -4664,13 +4154,6 @@ AUTH_DOCUMENTATION_URL = 'https://course-catalog-api-guide.readthedocs.io/en/lat # Affiliate cookie tracking AFFILIATE_COOKIE_NAME = 'dev_affiliate_id' -############## Settings for RedirectMiddleware ############### - -# Setting this to None causes Redirect data to never expire -# The cache is cleared when Redirect models are saved/deleted -REDIRECT_CACHE_TIMEOUT = None # The length of time we cache Redirect model data -REDIRECT_CACHE_KEY_PREFIX = 'redirects' - ############## Settings for LMS Context Sensitive Help ############## HELP_TOKENS_INI_FILE = REPO_ROOT / "lms" / "envs" / "help_tokens.ini" @@ -4713,7 +4196,6 @@ ENTERPRISE_CONSENT_API_URL = LMS_INTERNAL_ROOT_URL + '/consent/api/v1/' ENTERPRISE_SERVICE_WORKER_USERNAME = 'enterprise_worker' ENTERPRISE_API_CACHE_TIMEOUT = 3600 # Value is in seconds ENTERPRISE_CUSTOMER_LOGO_IMAGE_SIZE = 512 # Enterprise logo image size limit in KB's -ENTERPRISE_CATALOG_INTERNAL_ROOT_URL = 'http://enterprise.catalog.app:18160' # Defines the usernames of service users who should be throttled # at a higher rate than normal users when making requests of enterprise endpoints. ENTERPRISE_ALL_SERVICE_USERNAMES = [ @@ -4801,90 +4283,6 @@ ENTERPRISE_MARKETING_FOOTER_QUERY_PARAMS = {} ENTERPRISE_TAGLINE = '' TRANSCRIPT_LANG_CACHE_TIMEOUT = 60 * 60 * 24 # 24 hours -############## Settings for Course Enrollment Modes ###################### -# The min_price key refers to the minimum price allowed for an instance -# of a particular type of course enrollment mode. This is not to be confused -# with the min_price field of the CourseMode model, which refers to the actual -# price of the CourseMode. -COURSE_ENROLLMENT_MODES = { - "audit": { - "id": 1, - "slug": "audit", - "display_name": _("Audit"), - "min_price": 0, - }, - "verified": { - "id": 2, - "slug": "verified", - "display_name": _("Verified"), - "min_price": 1, - }, - "professional": { - "id": 3, - "slug": "professional", - "display_name": _("Professional"), - "min_price": 1, - }, - "no-id-professional": { - "id": 4, - "slug": "no-id-professional", - "display_name": _("No-Id-Professional"), - "min_price": 0, - }, - "credit": { - "id": 5, - "slug": "credit", - "display_name": _("Credit"), - "min_price": 0, - }, - "honor": { - "id": 6, - "slug": "honor", - "display_name": _("Honor"), - "min_price": 0, - }, - "masters": { - "id": 7, - "slug": "masters", - "display_name": _("Master's"), - "min_price": 0, - }, - "executive-education": { - "id": 8, - "slug": "executive-educations", - "display_name": _("Executive Education"), - "min_price": 1 - }, - "unpaid-executive-education": { - "id": 9, - "slug": "unpaid-executive-education", - "display_name": _("Unpaid Executive Education"), - "min_price": 0 - }, - "paid-executive-education": { - "id": 10, - "slug": "paid-executive-education", - "display_name": _("Paid Executive Education"), - "min_price": 1 - }, - "unpaid-bootcamp": { - "id": 11, - "slug": "unpaid-bootcamp", - "display_name": _("Unpaid Bootcamp"), - "min_price": 0 - }, - "paid-bootcamp": { - "id": 12, - "slug": "paid-bootcamp", - "display_name": _("Paid Bootcamp"), - "min_price": 1 - }, -} - -CONTENT_TYPE_GATE_GROUP_IDS = { - 'limited_access': 1, - 'full_access': 2, -} ############## Settings for the Discovery App ###################### @@ -5357,11 +4755,6 @@ IS_ELIGIBLE_FOR_FINANCIAL_ASSISTANCE_URL = '/core/api/course_eligibility/' FINANCIAL_ASSISTANCE_APPLICATION_STATUS_URL = "/core/api/financial_assistance_application/status/" CREATE_FINANCIAL_ASSISTANCE_APPLICATION_URL = '/core/api/financial_assistance_applications' -######################## Enterprise API Client ######################## -ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_KEY = "enterprise-backend-service-key" -ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_SECRET = "enterprise-backend-service-secret" -ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_PROVIDER_URL = "http://127.0.0.1:8000/oauth2" - # keys for big blue button live provider COURSE_LIVE_GLOBAL_CREDENTIALS = {} @@ -5604,94 +4997,6 @@ SURVEY_REPORT_EXTRA_DATA = {} LMS_COMM_DEFAULT_FROM_EMAIL = "no-reply@example.com" - -####################### Setting for built-in Blocks Extraction ####################### -# The following Django settings flags have been introduced temporarily to facilitate -# the rollout of the extracted built-in Blocks. Flags will use to toggle between -# the old and new block quickly without putting course content or user state at risk. -# -# Ticket: https://github.com/openedx/edx-platform/issues/35308 - -# .. toggle_name: USE_EXTRACTED_WORD_CLOUD_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted Word Cloud XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until https://github.com/openedx/edx-platform/issues/34840 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_WORD_CLOUD_BLOCK = False - -# .. toggle_name: USE_EXTRACTED_ANNOTATABLE_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted annotatable XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until https://github.com/openedx/edx-platform/issues/34841 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_ANNOTATABLE_BLOCK = False - -# .. toggle_name: USE_EXTRACTED_POLL_QUESTION_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted poll question XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until https://github.com/openedx/edx-platform/issues/34839 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_POLL_QUESTION_BLOCK = False - -# .. toggle_name: USE_EXTRACTED_LTI_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted LTI XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_LTI_BLOCK = False - -# .. toggle_name: USE_EXTRACTED_HTML_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted HTML XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_HTML_BLOCK = False - -# .. toggle_name: USE_EXTRACTED_DISCUSSION_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted Discussion XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_DISCUSSION_BLOCK = False - -# .. toggle_name: USE_EXTRACTED_PROBLEM_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted Problem XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_PROBLEM_BLOCK = False - -# .. toggle_name: USE_EXTRACTED_VIDEO_BLOCK -# .. toggle_default: False -# .. toggle_implementation: DjangoSetting -# .. toggle_description: Enables the use of the extracted Video XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. -# .. toggle_use_cases: temporary -# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. -# .. toggle_creation_date: 2024-11-10 -# .. toggle_target_removal_date: 2025-06-01 -USE_EXTRACTED_VIDEO_BLOCK = False - # .. setting_name: RECAPTCHA_PRIVATE_KEY # .. setting_default: empty string # .. setting_description: Add recaptcha private key to use captcha feature in discussion app. diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index 4785bdb042..3934a470c6 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -469,19 +469,19 @@ DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL = True # If you want to enable theming in devstack, uncomment this section and add any relevant # theme directories to COMPREHENSIVE_THEME_DIRS -# We have to import the private method here because production.py calls -# derive_settings('lms.envs.production') which runs _make_mako_template_dirs with +# We have to import the make_mako_template_dirs method here because production.py calls +# derive_settings('lms.envs.production') which runs make_mako_template_dirs with # the settings from production, which doesn't include these theming settings. Thus, # the templating engine is unable to find the themed templates because they don't exist # in it's path. Re-calling derive_settings doesn't work because the settings was already # changed from a function to a list, and it can't be derived again. -# from .common import _make_mako_template_dirs +# from openedx.envs.common import make_mako_template_dirs # ENABLE_COMPREHENSIVE_THEMING = True # COMPREHENSIVE_THEME_DIRS = [ # "/edx/app/edxapp/edx-platform/themes/" # ] -# TEMPLATES[1]["DIRS"] = _make_mako_template_dirs +# TEMPLATES[1]["DIRS"] = make_mako_template_dirs # derive_settings(__name__) # Uncomment the lines below if you'd like to see SQL statements in your devstack LMS log. diff --git a/lms/envs/docs/README.rst b/lms/envs/docs/README.rst index 5a5c78bb73..b0a4b42d10 100644 --- a/lms/envs/docs/README.rst +++ b/lms/envs/docs/README.rst @@ -1,7 +1,7 @@ LMS Configuration Settings ########################## -The ``lms.envs`` module contains project-wide settings, defined in python modules +The ``lms.envs`` module contains lms related settings, defined in python modules using the standard `Django Settings`_ mechanism, plus some Open edX particularities, which we describe below. @@ -70,7 +70,7 @@ when nested within each other: .. code-block:: python - def _make_mako_template_dirs(settings): + def make_mako_template_dirs(settings): """ Derives the final Mako template directories list from other settings. """ @@ -91,6 +91,6 @@ when nested within each other: 'NAME': 'mako', 'BACKEND': 'common.djangoapps.edxmako.backend.Mako', 'APP_DIRS': False, - 'DIRS': Derived(_make_mako_template_dirs), + 'DIRS': Derived(make_mako_template_dirs), }, ] diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_register.py b/openedx/core/djangoapps/user_authn/views/tests/test_register.py index 396513f496..136adc01f7 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_register.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_register.py @@ -2962,7 +2962,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase, OpenEdxEventsTestM ) ]) def test_password_empty_validation_decision(self): - # 2 is the default setting for minimum length found in lms/envs/common.py + # 2 is the default setting for minimum length found in openedx/envs/common.py # under AUTH_PASSWORD_VALIDATORS.MinimumLengthValidator msg = 'This password is too short. It must contain at least 4 characters.' self.assertValidationDecision( @@ -2977,7 +2977,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase, OpenEdxEventsTestM ]) def test_password_bad_min_length_validation_decision(self): password = 'p' - # 2 is the default setting for minimum length found in lms/envs/common.py + # 2 is the default setting for minimum length found in openedx/envs/common.py # under AUTH_PASSWORD_VALIDATORS.MinimumLengthValidator msg = 'This password is too short. It must contain at least 4 characters.' self.assertValidationDecision( @@ -2987,7 +2987,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase, OpenEdxEventsTestM def test_password_bad_max_length_validation_decision(self): password = 'p' * DEFAULT_MAX_PASSWORD_LENGTH - # 75 is the default setting for maximum length found in lms/envs/common.py + # 75 is the default setting for maximum length found in openedx/envs/common.py # under AUTH_PASSWORD_VALIDATORS.MaximumLengthValidator msg = 'This password is too long. It must contain no more than 75 characters.' self.assertValidationDecision( diff --git a/openedx/envs/__init__.py b/openedx/envs/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openedx/envs/common.py b/openedx/envs/common.py new file mode 100644 index 0000000000..15fc835f1c --- /dev/null +++ b/openedx/envs/common.py @@ -0,0 +1,788 @@ +""" +Common Django settings for Open edX services. + +This module defines configuration shared between the LMS and CMS (Studio) +environments. It centralizes common settings in one place and reduces duplication. + +Service-specific settings should import from this module and override as needed. + +Note: More settings will be added to this file as the effort to simplify +settings moves forward. See docs/decisions/0022-settings-simplification.rst for +more details on the effort to simplify settings across Open edX services. + +To create section headers in this file, use the following function: + +```python +def center_with_hashes(text: str, width: int = 76): + print(f"{f' {text} ':#^{width}}") +``` +""" +import os +from path import Path as path + +from django.utils.translation import gettext_lazy as _ + +from openedx.core.lib.derived import Derived + +from openedx.core.djangoapps.theming.helpers_dirs import ( + get_themes_unchecked, + get_theme_base_dirs_from_settings +) + +from openedx.core.constants import ( # pylint: disable=unused-import + ASSET_KEY_PATTERN, + COURSE_KEY_REGEX, + COURSE_KEY_PATTERN, + COURSE_ID_PATTERN, + USAGE_KEY_PATTERN, + USAGE_ID_PATTERN, +) + +################ Shared Functions for Derived Configuration ################ + + +def make_mako_template_dirs(settings): + """ + Derives the final list of Mako template directories based on the provided settings. + + Args: + settings: A Django settings module object. + + Returns: + list: A list of Mako template directories, potentially updated with additional + theme directories. + """ + if settings.ENABLE_COMPREHENSIVE_THEMING: + themes_dirs = get_theme_base_dirs_from_settings(settings.COMPREHENSIVE_THEME_DIRS) + for theme in get_themes_unchecked(themes_dirs, settings.PROJECT_ROOT): + if theme.themes_base_dir not in settings.MAKO_TEMPLATE_DIRS_BASE: + settings.MAKO_TEMPLATE_DIRS_BASE.insert(0, theme.themes_base_dir) + return settings.MAKO_TEMPLATE_DIRS_BASE + + +def _make_locale_paths(settings): + """ + Constructs a list of paths to locale directories used for translation. + + Localization (l10n) strings (e.g. django.po) are found in these directories. + + Args: + settings: A Django settings module object. + + Returns: + list: A list of paths, `str` or `path.Path`, to locale directories. + """ + locale_paths = list(settings.PREPEND_LOCALE_PATHS) + locale_paths += [settings.REPO_ROOT + '/conf/locale'] # edx-platform/conf/locale/ + + if settings.ENABLE_COMPREHENSIVE_THEMING: + # Add locale paths to settings for comprehensive theming. + for locale_path in settings.COMPREHENSIVE_THEME_LOCALE_PATHS: + locale_paths += (path(locale_path), ) + return locale_paths + +############################# Django Built-Ins ############################# + +USE_TZ = True + +# User-uploaded content +MEDIA_ROOT = '/edx/var/edxapp/media/' +MEDIA_URL = '/media/' + +# Dummy secret key for dev/test +SECRET_KEY = 'dev key' + +STATICI18N_OUTPUT_DIR = "js/i18n" + +# Sourced from http://www.localeplanet.com/icu/ and wikipedia +LANGUAGES = [ + ('en', 'English'), + ('rtl', 'Right-to-Left Test Language'), + ('eo', 'Dummy Language (Esperanto)'), # Dummy languaged used for testing + + ('am', 'አማርኛ'), # Amharic + ('ar', 'العربية'), # Arabic + ('az', 'azərbaycanca'), # Azerbaijani + ('bg-bg', 'български (България)'), # Bulgarian (Bulgaria) + ('bn-bd', 'বাংলা (বাংলাদেশ)'), # Bengali (Bangladesh) + ('bn-in', 'বাংলা (ভারত)'), # Bengali (India) + ('bs', 'bosanski'), # Bosnian + ('ca', 'Català'), # Catalan + ('ca@valencia', 'Català (València)'), # Catalan (Valencia) + ('cs', 'Čeština'), # Czech + ('cy', 'Cymraeg'), # Welsh + ('da', 'dansk'), # Danish + ('de-de', 'Deutsch (Deutschland)'), # German (Germany) + ('el', 'Ελληνικά'), # Greek + ('en-uk', 'English (United Kingdom)'), # English (United Kingdom) + ('en@lolcat', 'LOLCAT English'), # LOLCAT English + ('en@pirate', 'Pirate English'), # Pirate English + ('es-419', 'Español (Latinoamérica)'), # Spanish (Latin America) + ('es-ar', 'Español (Argentina)'), # Spanish (Argentina) + ('es-ec', 'Español (Ecuador)'), # Spanish (Ecuador) + ('es-es', 'Español (España)'), # Spanish (Spain) + ('es-mx', 'Español (México)'), # Spanish (Mexico) + ('es-pe', 'Español (Perú)'), # Spanish (Peru) + ('et-ee', 'Eesti (Eesti)'), # Estonian (Estonia) + ('eu-es', 'euskara (Espainia)'), # Basque (Spain) + ('fa', 'فارسی'), # Persian + ('fa-ir', 'فارسی (ایران)'), # Persian (Iran) + ('fi-fi', 'Suomi (Suomi)'), # Finnish (Finland) + ('fil', 'Filipino'), # Filipino + ('fr', 'Français'), # French + ('gl', 'Galego'), # Galician + ('gu', 'ગુજરાતી'), # Gujarati + ('he', 'עברית'), # Hebrew + ('hi', 'हिन्दी'), # Hindi + ('hr', 'hrvatski'), # Croatian + ('hu', 'magyar'), # Hungarian + ('hy-am', 'Հայերեն (Հայաստան)'), # Armenian (Armenia) + ('id', 'Bahasa Indonesia'), # Indonesian + ('it-it', 'Italiano (Italia)'), # Italian (Italy) + ('ja-jp', '日本語 (日本)'), # Japanese (Japan) + ('kk-kz', 'қазақ тілі (Қазақстан)'), # Kazakh (Kazakhstan) + ('km-kh', 'ភាសាខ្មែរ (កម្ពុជា)'), # Khmer (Cambodia) + ('kn', 'ಕನ್ನಡ'), # Kannada + ('ko-kr', '한국어 (대한민국)'), # Korean (Korea) + ('lt-lt', 'Lietuvių (Lietuva)'), # Lithuanian (Lithuania) + ('ml', 'മലയാളം'), # Malayalam + ('mn', 'Монгол хэл'), # Mongolian + ('mr', 'मराठी'), # Marathi + ('ms', 'Bahasa Melayu'), # Malay + ('nb', 'Norsk bokmål'), # Norwegian Bokmål + ('ne', 'नेपाली'), # Nepali + ('nl-nl', 'Nederlands (Nederland)'), # Dutch (Netherlands) + ('or', 'ଓଡ଼ିଆ'), # Oriya + ('pl', 'Polski'), # Polish + ('pt-br', 'Português (Brasil)'), # Portuguese (Brazil) + ('pt-pt', 'Português (Portugal)'), # Portuguese (Portugal) + ('ro', 'română'), # Romanian + ('ru', 'Русский'), # Russian + ('si', 'සිංහල'), # Sinhala + ('sk', 'Slovenčina'), # Slovak + ('sl', 'Slovenščina'), # Slovenian + ('sq', 'shqip'), # Albanian + ('sr', 'Српски'), # Serbian + ('sv', 'svenska'), # Swedish + ('sw', 'Kiswahili'), # Swahili + ('ta', 'தமிழ்'), # Tamil + ('te', 'తెలుగు'), # Telugu + ('th', 'ไทย'), # Thai + ('tr-tr', 'Türkçe (Türkiye)'), # Turkish (Turkey) + ('uk', 'Українська'), # Ukranian + ('ur', 'اردو'), # Urdu + ('vi', 'Tiếng Việt'), # Vietnamese + ('uz', 'Ўзбек'), # Uzbek + ('zh-cn', '中文 (简体)'), # Chinese (China) + ('zh-hk', '中文 (香港)'), # Chinese (Hong Kong) + ('zh-tw', '中文 (台灣)'), # Chinese (Taiwan) +] + +# these languages display right to left +LANGUAGES_BIDI = ("he", "ar", "fa", "ur", "fa-ir", "rtl") + +LANGUAGE_COOKIE_NAME = "openedx-language-preference" + +LOCALE_PATHS = Derived(_make_locale_paths) + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "common.djangoapps.util.password_policy_validators.MinimumLengthValidator", + "OPTIONS": { + "min_length": 8 + } + }, + { + "NAME": "common.djangoapps.util.password_policy_validators.MaximumLengthValidator", + "OPTIONS": { + "max_length": 75 + } + }, +] + +# See https://github.com/openedx/edx-django-sites-extensions for more info. +# Default site to use if site matching request headers does not exist. +SITE_ID = 1 + +################################# Language ################################# + +# Source: +# http://loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt according to http://en.wikipedia.org/wiki/ISO_639-1 +# Note that this is used as the set of choices to the `code` field of the `LanguageProficiency` model. +ALL_LANGUAGES = [ + ["aa", "Afar"], + ["ab", "Abkhazian"], + ["af", "Afrikaans"], + ["ak", "Akan"], + ["sq", "Albanian"], + ["am", "Amharic"], + ["ar", "Arabic"], + ["an", "Aragonese"], + ["hy", "Armenian"], + ["as", "Assamese"], + ["av", "Avaric"], + ["ae", "Avestan"], + ["ay", "Aymara"], + ["az", "Azerbaijani"], + ["ba", "Bashkir"], + ["bm", "Bambara"], + ["eu", "Basque"], + ["be", "Belarusian"], + ["bn", "Bengali"], + ["bh", "Bihari languages"], + ["bi", "Bislama"], + ["bs", "Bosnian"], + ["br", "Breton"], + ["bg", "Bulgarian"], + ["my", "Burmese"], + ["ca", "Catalan"], + ["ch", "Chamorro"], + ["ce", "Chechen"], + ["zh", "Chinese"], + ["zh_HANS", "Simplified Chinese"], + ["zh_HANT", "Traditional Chinese"], + ["cu", "Church Slavic"], + ["cv", "Chuvash"], + ["kw", "Cornish"], + ["co", "Corsican"], + ["cr", "Cree"], + ["cs", "Czech"], + ["da", "Danish"], + ["dv", "Divehi"], + ["nl", "Dutch"], + ["dz", "Dzongkha"], + ["en", "English"], + ["eo", "Esperanto"], + ["et", "Estonian"], + ["ee", "Ewe"], + ["fo", "Faroese"], + ["fj", "Fijian"], + ["fi", "Finnish"], + ["fr", "French"], + ["fy", "Western Frisian"], + ["ff", "Fulah"], + ["ka", "Georgian"], + ["de", "German"], + ["gd", "Gaelic"], + ["ga", "Irish"], + ["gl", "Galician"], + ["gv", "Manx"], + ["el", "Greek"], + ["gn", "Guarani"], + ["gu", "Gujarati"], + ["ht", "Haitian"], + ["ha", "Hausa"], + ["he", "Hebrew"], + ["hz", "Herero"], + ["hi", "Hindi"], + ["ho", "Hiri Motu"], + ["hr", "Croatian"], + ["hu", "Hungarian"], + ["ig", "Igbo"], + ["is", "Icelandic"], + ["io", "Ido"], + ["ii", "Sichuan Yi"], + ["iu", "Inuktitut"], + ["ie", "Interlingue"], + ["ia", "Interlingua"], + ["id", "Indonesian"], + ["ik", "Inupiaq"], + ["it", "Italian"], + ["jv", "Javanese"], + ["ja", "Japanese"], + ["kl", "Kalaallisut"], + ["kn", "Kannada"], + ["ks", "Kashmiri"], + ["kr", "Kanuri"], + ["kk", "Kazakh"], + ["km", "Central Khmer"], + ["ki", "Kikuyu"], + ["rw", "Kinyarwanda"], + ["ky", "Kirghiz"], + ["kv", "Komi"], + ["kg", "Kongo"], + ["ko", "Korean"], + ["kj", "Kuanyama"], + ["ku", "Kurdish"], + ["lo", "Lao"], + ["la", "Latin"], + ["lv", "Latvian"], + ["li", "Limburgan"], + ["ln", "Lingala"], + ["lt", "Lithuanian"], + ["lb", "Luxembourgish"], + ["lu", "Luba-Katanga"], + ["lg", "Ganda"], + ["mk", "Macedonian"], + ["mh", "Marshallese"], + ["ml", "Malayalam"], + ["mi", "Maori"], + ["mr", "Marathi"], + ["ms", "Malay"], + ["mg", "Malagasy"], + ["mt", "Maltese"], + ["mn", "Mongolian"], + ["na", "Nauru"], + ["nv", "Navajo"], + ["nr", "Ndebele, South"], + ["nd", "Ndebele, North"], + ["ng", "Ndonga"], + ["ne", "Nepali"], + ["nn", "Norwegian Nynorsk"], + ["nb", "Bokmål, Norwegian"], + ["no", "Norwegian"], + ["ny", "Chichewa"], + ["oc", "Occitan"], + ["oj", "Ojibwa"], + ["or", "Oriya"], + ["om", "Oromo"], + ["os", "Ossetian"], + ["pa", "Panjabi"], + ["fa", "Persian"], + ["pi", "Pali"], + ["pl", "Polish"], + ["pt", "Portuguese"], + ["ps", "Pushto"], + ["qu", "Quechua"], + ["rm", "Romansh"], + ["ro", "Romanian"], + ["rn", "Rundi"], + ["ru", "Russian"], + ["sg", "Sango"], + ["sa", "Sanskrit"], + ["si", "Sinhala"], + ["sk", "Slovak"], + ["sl", "Slovenian"], + ["se", "Northern Sami"], + ["sm", "Samoan"], + ["sn", "Shona"], + ["sd", "Sindhi"], + ["so", "Somali"], + ["st", "Sotho, Southern"], + ["es", "Spanish"], + ["sc", "Sardinian"], + ["sr", "Serbian"], + ["ss", "Swati"], + ["su", "Sundanese"], + ["sw", "Swahili"], + ["sv", "Swedish"], + ["ty", "Tahitian"], + ["ta", "Tamil"], + ["tt", "Tatar"], + ["te", "Telugu"], + ["tg", "Tajik"], + ["tl", "Tagalog"], + ["th", "Thai"], + ["bo", "Tibetan"], + ["ti", "Tigrinya"], + ["to", "Tonga (Tonga Islands)"], + ["tn", "Tswana"], + ["ts", "Tsonga"], + ["tk", "Turkmen"], + ["tr", "Turkish"], + ["tw", "Twi"], + ["ug", "Uighur"], + ["uk", "Ukrainian"], + ["ur", "Urdu"], + ["uz", "Uzbek"], + ["ve", "Venda"], + ["vi", "Vietnamese"], + ["vo", "Volapük"], + ["cy", "Welsh"], + ["wa", "Walloon"], + ["wo", "Wolof"], + ["xh", "Xhosa"], + ["yi", "Yiddish"], + ["yo", "Yoruba"], + ["za", "Zhuang"], + ["zu", "Zulu"] +] + +LANGUAGE_DICT = dict(LANGUAGES) + +########################## Django Rest Framework ########################### + +REST_FRAMEWORK = { + # These default classes add observability around endpoints using defaults, and should + # not be used anywhere else. + # Notes on Order: + # 1. `JwtAuthentication` does not check `is_active`, so email validation does not affect it. However, + # `SessionAuthentication` does. These work differently, and order changes in what way, which really stinks. See + # https://github.com/openedx/public-engineering/issues/165 for details. + # 2. `JwtAuthentication` may also update the database based on contents. Since the LMS creates these JWTs, this + # shouldn't have any affect at this time. But it could, when and if another service started creating the JWTs. + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'openedx.core.djangolib.default_auth_classes.DefaultJwtAuthentication', + 'openedx.core.djangolib.default_auth_classes.DefaultSessionAuthentication', + ], + 'DEFAULT_PAGINATION_CLASS': 'edx_rest_framework_extensions.paginators.DefaultPagination', + 'DEFAULT_RENDERER_CLASSES': ( + 'rest_framework.renderers.JSONRenderer', + ), + 'EXCEPTION_HANDLER': 'openedx.core.lib.request_utils.ignored_error_exception_handler', + 'PAGE_SIZE': 10, + 'URL_FORMAT_OVERRIDE': None, + 'DEFAULT_THROTTLE_RATES': { + 'user': '60/minute', + 'service_user': '800/minute', + 'registration_validation': '30/minute', + 'high_service_user': '2000/minute', + }, +} + +################################ Heartbeat ################################# + +# Checks run in normal mode by the heartbeat djangoapp +HEARTBEAT_CHECKS = [ + 'openedx.core.djangoapps.heartbeat.default_checks.check_modulestore', + 'openedx.core.djangoapps.heartbeat.default_checks.check_database', +] + +# Other checks to run by default in "extended"/heavy mode +HEARTBEAT_EXTENDED_CHECKS = ( + 'openedx.core.djangoapps.heartbeat.default_checks.check_celery', +) + +HEARTBEAT_CELERY_TIMEOUT = 5 + +############################ RedirectMiddleware ############################ + +# Setting this to None causes Redirect data to never expire +# The cache is cleared when Redirect models are saved/deleted +REDIRECT_CACHE_TIMEOUT = None # The length of time we cache Redirect model data +REDIRECT_CACHE_KEY_PREFIX = 'redirects' + +########################### Django Debug Toolbar ########################### + +# We don't enable Django Debug Toolbar universally, but whenever we do, we want +# to avoid patching settings. Patched settings can cause circular import +# problems: https://django-debug-toolbar.readthedocs.org/en/1.0/installation.html#explicit-setup + +DEBUG_TOOLBAR_PATCH_SETTINGS = False + +################################### JWT #################################### + +JWT_AUTH = { + 'JWT_VERIFY_EXPIRATION': True, + + 'JWT_PAYLOAD_GET_USERNAME_HANDLER': lambda d: d.get('username'), + 'JWT_LEEWAY': 1, + 'JWT_DECODE_HANDLER': 'edx_rest_framework_extensions.auth.jwt.decoder.jwt_decode_handler', + + 'JWT_AUTH_COOKIE': 'edx-jwt-cookie', + + # Number of seconds before JWTs expire + 'JWT_EXPIRATION': 30, + 'JWT_IN_COOKIE_EXPIRATION': 60 * 60, + + 'JWT_LOGIN_CLIENT_ID': 'login-service-client-id', + 'JWT_LOGIN_SERVICE_USERNAME': 'login_service_user', + + 'JWT_SUPPORTED_VERSION': '1.2.0', + + 'JWT_ALGORITHM': 'HS256', + 'JWT_SECRET_KEY': SECRET_KEY, + + 'JWT_SIGNING_ALGORITHM': 'RS512', + 'JWT_PRIVATE_SIGNING_JWK': None, + 'JWT_PUBLIC_SIGNING_JWK_SET': None, + + 'JWT_ISSUER': 'http://127.0.0.1:8000/oauth2', + 'JWT_AUDIENCE': 'change-me', + 'JWT_ISSUERS': [ + { + 'ISSUER': 'http://127.0.0.1:8000/oauth2', + 'AUDIENCE': 'change-me', + 'SECRET_KEY': SECRET_KEY + } + ], + 'JWT_AUTH_COOKIE_HEADER_PAYLOAD': 'edx-jwt-cookie-header-payload', + 'JWT_AUTH_COOKIE_SIGNATURE': 'edx-jwt-cookie-signature', + 'JWT_AUTH_HEADER_PREFIX': 'JWT', +} + +############################ Parental Controls ############################# + +# .. setting_name: PARENTAL_CONSENT_AGE_LIMIT +# .. setting_default: 13 +# .. setting_description: The age at which a learner no longer requires parental consent, +# or ``None`` if parental consent is never required. +PARENTAL_CONSENT_AGE_LIMIT = 13 + +############################### Registration ############################### + +# .. setting_name: REGISTRATION_EMAIL_PATTERNS_ALLOWED +# .. setting_default: None +# .. setting_description: Optional setting to restrict registration / account creation +# to only emails that match a regex in this list. Set to ``None`` to allow any email (default). +REGISTRATION_EMAIL_PATTERNS_ALLOWED = None + +######################### Course Enrollment Modes ########################## + +# The min_price key refers to the minimum price allowed for an instance +# of a particular type of course enrollment mode. This is not to be confused +# with the min_price field of the CourseMode model, which refers to the actual +# price of the CourseMode. +COURSE_ENROLLMENT_MODES = { + "audit": { + "id": 1, + "slug": "audit", + "display_name": _("Audit"), + "min_price": 0, + }, + "verified": { + "id": 2, + "slug": "verified", + "display_name": _("Verified"), + "min_price": 1, + }, + "professional": { + "id": 3, + "slug": "professional", + "display_name": _("Professional"), + "min_price": 1, + }, + "no-id-professional": { + "id": 4, + "slug": "no-id-professional", + "display_name": _("No-Id-Professional"), + "min_price": 0, + }, + "credit": { + "id": 5, + "slug": "credit", + "display_name": _("Credit"), + "min_price": 0, + }, + "honor": { + "id": 6, + "slug": "honor", + "display_name": _("Honor"), + "min_price": 0, + }, + "masters": { + "id": 7, + "slug": "masters", + "display_name": _("Master's"), + "min_price": 0, + }, + "executive-education": { + "id": 8, + "slug": "executive-educations", + "display_name": _("Executive Education"), + "min_price": 1 + }, + "unpaid-executive-education": { + "id": 9, + "slug": "unpaid-executive-education", + "display_name": _("Unpaid Executive Education"), + "min_price": 0 + }, + "paid-executive-education": { + "id": 10, + "slug": "paid-executive-education", + "display_name": _("Paid Executive Education"), + "min_price": 1 + }, + "unpaid-bootcamp": { + "id": 11, + "slug": "unpaid-bootcamp", + "display_name": _("Unpaid Bootcamp"), + "min_price": 0 + }, + "paid-bootcamp": { + "id": 12, + "slug": "paid-bootcamp", + "display_name": _("Paid Bootcamp"), + "min_price": 1 + }, +} + +CONTENT_TYPE_GATE_GROUP_IDS = { + 'limited_access': 1, + 'full_access': 2, +} + +########################## Enterprise Api Client ########################### + +ENTERPRISE_CATALOG_INTERNAL_ROOT_URL = 'http://enterprise.catalog.app:18160' + +ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_KEY = "enterprise-backend-service-key" +ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_SECRET = "enterprise-backend-service-secret" +ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_PROVIDER_URL = "http://127.0.0.1:8000/oauth2" + + +############################### ModuleStore ################################ + +ASSET_IGNORE_REGEX = r"(^\._.*$)|(^\.DS_Store$)|(^.*~$)" + +########################### Django OAuth Toolkit ########################### + +# This is required for the migrations in oauth_dispatch.models +# otherwise it fails saying this attribute is not present in Settings + +# Although Studio does not enable OAuth2 Provider capability, the new approach +# to generating test databases will discover and try to create all tables +# and this setting needs to be present + +OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application' + +############################## Profile Image ############################### + +# The following PROFILE_IMAGE_* settings are included as common settings as +# they are indirectly accessed through the email opt-in API, which is +# technically accessible through the CMS via legacy URLs. + +# WARNING: Certain django storage backends do not support atomic +# file overwrites (including the default, OverwriteStorage) - instead +# there are separate calls to delete and then write a new file in the +# storage backend. This introduces the risk of a race condition +# occurring when a user uploads a new profile image to replace an +# earlier one (the file will temporarily be deleted). +PROFILE_IMAGE_BACKEND = { + 'class': 'openedx.core.storage.OverwriteStorage', + 'options': { + 'location': os.path.join(MEDIA_ROOT, 'profile-images/'), + 'base_url': os.path.join(MEDIA_URL, 'profile-images/'), + }, +} +PROFILE_IMAGE_DEFAULT_FILENAME = 'images/profiles/default' +PROFILE_IMAGE_DEFAULT_FILE_EXTENSION = 'png' +# This key is used in generating unguessable URLs to users' +# profile images. Once it has been set, changing it will make the +# platform unaware of current image URLs. +PROFILE_IMAGE_HASH_SEED = 'placeholder_secret_key' +PROFILE_IMAGE_MAX_BYTES = 1024 * 1024 +PROFILE_IMAGE_MIN_BYTES = 100 +PROFILE_IMAGE_SIZES_MAP = { + 'full': 500, + 'large': 120, + 'medium': 50, + 'small': 30 +} + +######################## Built-in Blocks Extraction ######################## + +# The following Django settings flags have been introduced temporarily to facilitate +# the rollout of the extracted built-in Blocks. Flags will use to toggle between +# the old and new block quickly without putting course content or user state at risk. +# +# Ticket: https://github.com/openedx/edx-platform/issues/35308 + +# .. toggle_name: USE_EXTRACTED_WORD_CLOUD_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted Word Cloud XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until https://github.com/openedx/edx-platform/issues/34840 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_WORD_CLOUD_BLOCK = False + +# .. toggle_name: USE_EXTRACTED_ANNOTATABLE_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted annotatable XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until https://github.com/openedx/edx-platform/issues/34841 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_ANNOTATABLE_BLOCK = False + +# .. toggle_name: USE_EXTRACTED_POLL_QUESTION_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted poll question XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until https://github.com/openedx/edx-platform/issues/34839 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_POLL_QUESTION_BLOCK = False + +# .. toggle_name: USE_EXTRACTED_LTI_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted LTI XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_LTI_BLOCK = False + +# .. toggle_name: USE_EXTRACTED_HTML_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted HTML XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_HTML_BLOCK = False + +# .. toggle_name: USE_EXTRACTED_DISCUSSION_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted Discussion XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_DISCUSSION_BLOCK = False + +# .. toggle_name: USE_EXTRACTED_PROBLEM_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted Problem XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_PROBLEM_BLOCK = False + +# .. toggle_name: USE_EXTRACTED_VIDEO_BLOCK +# .. toggle_default: False +# .. toggle_implementation: DjangoSetting +# .. toggle_description: Enables the use of the extracted Video XBlock, which has been shifted to the 'openedx/xblocks-contrib' repo. +# .. toggle_use_cases: temporary +# .. toggle_warning: Not production-ready until relevant subtask https://github.com/openedx/edx-platform/issues/34827 is done. +# .. toggle_creation_date: 2024-11-10 +# .. toggle_target_removal_date: 2025-06-01 +USE_EXTRACTED_VIDEO_BLOCK = False + +############################## Miscellaneous ############################### + +COURSE_MODE_DEFAULTS = { + 'android_sku': None, + 'bulk_sku': None, + 'currency': 'usd', + 'description': None, + 'expiration_datetime': None, + 'ios_sku': None, + 'min_price': 0, + 'name': _('Audit'), + 'sku': None, + 'slug': 'audit', + 'suggested_prices': '', +} + +DEFAULT_COURSE_ABOUT_IMAGE_URL = 'images/pencils.jpg' + +DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH = "verify_student_disable_account_activation_requirement" + +# If this is true, random scores will be generated for the purpose of debugging the profile graphs +GENERATE_PROFILE_SCORES = False + +# The space is required for space-dependent languages like Arabic and Farsi. +# However, backward compatibility with Ficus older releases is still maintained (space is still not valid) +# in the AccountCreationForm and the user_api through the ENABLE_UNICODE_USERNAME feature flag. +USERNAME_REGEX_PARTIAL = r'[\w .@_+-]+' +USERNAME_PATTERN = fr'(?P{USERNAME_REGEX_PARTIAL})' + +# These are standard regexes for pulling out info like course_ids, usage_ids, etc. +# They are used so that URLs with deprecated-format strings still work. +USAGE_KEY_PATTERN = r'(?P(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))' +ASSET_KEY_PATTERN = r'(?P(?:/?c4x(:/)?/[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))' +USAGE_ID_PATTERN = r'(?P(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))' diff --git a/scripts/vulture/find-dead-code.sh b/scripts/vulture/find-dead-code.sh index c78793ec3a..aec5a4316a 100755 --- a/scripts/vulture/find-dead-code.sh +++ b/scripts/vulture/find-dead-code.sh @@ -37,7 +37,7 @@ echo '' > "$OUTPUT_FILE" # exclude test code from analysis, as it isn't explicitly called by other # code. Additionally, application code that is only called by tests # should be considered dead -EXCLUSIONS='/test,/acceptance,cms/envs,lms/envs,migrations/,signals.py' +EXCLUSIONS='/test,/acceptance,cms/envs,lms/envs,openedx/envs,migrations/,signals.py' MIN_CONFIDENCE=90 # paths to the code on which to run the analysis CODE_PATHS=('cms' 'common' 'lms' 'openedx') diff --git a/setup.cfg b/setup.cfg index f1411017d8..e4419bd149 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,7 +20,7 @@ filterwarnings = ignore:'etree' is deprecated. Use 'xml.etree.ElementTree' instead.:DeprecationWarning:wiki junit_family = xunit2 -norecursedirs = .* *.egg build conf dist node_modules test_root cms/envs lms/envs +norecursedirs = .* *.egg build conf dist node_modules test_root cms/envs lms/envs openedx/envs python_classes = python_files = tests.py test_*.py tests_*.py *_tests.py __init__.py