Files
edx-platform/cms/envs/devstack.py
2024-05-17 18:55:16 +05:00

352 lines
14 KiB
Python

"""
Specific overrides to the base prod settings to make development easier.
"""
import logging
from os.path import abspath, dirname, join
from .production import * # pylint: disable=wildcard-import, unused-wildcard-import
# Don't use S3 in devstack, fall back to filesystem
del DEFAULT_FILE_STORAGE
COURSE_IMPORT_EXPORT_STORAGE = 'django.core.files.storage.FileSystemStorage'
USER_TASKS_ARTIFACT_STORAGE = COURSE_IMPORT_EXPORT_STORAGE
DEBUG = True
USE_I18N = True
DEFAULT_TEMPLATE_ENGINE['OPTIONS']['debug'] = DEBUG
SITE_NAME = 'localhost:8001'
HTTPS = 'off'
CMS_BASE = 'localhost:18010'
SESSION_COOKIE_NAME = 'studio_sessionid'
################################ LOGGERS ######################################
# Disable noisy loggers
for pkg_name in ['common.djangoapps.track.contexts', 'common.djangoapps.track.middleware']:
logging.getLogger(pkg_name).setLevel(logging.CRITICAL)
# Docker does not support the syslog socket at /dev/log. Rely on the console.
LOGGING['handlers']['local'] = LOGGING['handlers']['tracking'] = {
'class': 'logging.NullHandler',
}
LOGGING['loggers']['tracking']['handlers'] = ['console']
################################ EMAIL ########################################
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/edx/src/ace_messages/'
################################# LMS INTEGRATION #############################
LMS_BASE = 'localhost:18000'
LMS_ROOT_URL = f'http://{LMS_BASE}'
FEATURES['PREVIEW_LMS_BASE'] = "preview." + LMS_BASE
FRONTEND_REGISTER_URL = LMS_ROOT_URL + '/register'
################################## Video Pipeline Settings #########################
FEATURES['ENABLE_VIDEO_UPLOAD_PIPELINE'] = True
########################### PIPELINE #################################
# Skip packaging and optimization in development
PIPELINE['PIPELINE_ENABLED'] = False
STATICFILES_STORAGE = 'openedx.core.storage.DevelopmentStorage'
# Revert to the default set of finders as we don't want the production pipeline
STATICFILES_FINDERS = [
'openedx.core.djangoapps.theming.finders.ThemeFilesFinder',
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]
# Load development webpack donfiguration
WEBPACK_CONFIG_PATH = 'webpack.dev.config.js'
############################ PYFS XBLOCKS SERVICE #############################
# Set configuration for Django pyfilesystem
DJFS = {
'type': 'osfs',
'directory_root': 'cms/static/djpyfs',
'url_root': '/static/djpyfs',
}
################################# CELERY ######################################
# By default don't use a worker, execute tasks as if they were local functions
CELERY_ALWAYS_EAGER = True
# When the celery task is eagerly, it is executed locally while sharing the
# thread and its request cache with the active Django Request. In that case,
# do not clear the cache.
CLEAR_REQUEST_CACHE_ON_TASK_COMPLETION = False
################################ DEBUG TOOLBAR ################################
INSTALLED_APPS += ['debug_toolbar']
MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
INTERNAL_IPS = ('127.0.0.1',)
DEBUG_TOOLBAR_PANELS = (
'debug_toolbar.panels.versions.VersionsPanel',
'debug_toolbar.panels.timer.TimerPanel',
'debug_toolbar.panels.settings.SettingsPanel',
'debug_toolbar.panels.headers.HeadersPanel',
'debug_toolbar.panels.request.RequestPanel',
'debug_toolbar.panels.sql.SQLPanel',
'debug_toolbar.panels.signals.SignalsPanel',
'debug_toolbar.panels.profiling.ProfilingPanel',
'debug_toolbar.panels.history.HistoryPanel',
)
DEBUG_TOOLBAR_CONFIG = {
# Profile panel is incompatible with wrapped views
# See https://github.com/jazzband/django-debug-toolbar/issues/792
'DISABLE_PANELS': (
'debug_toolbar.panels.profiling.ProfilingPanel',
),
'SHOW_TOOLBAR_CALLBACK': 'cms.envs.devstack.should_show_debug_toolbar',
}
def should_show_debug_toolbar(request): # lint-amnesty, pylint: disable=missing-function-docstring
# We always want the toolbar on devstack unless running tests from another Docker container
hostname = request.get_host()
if hostname.startswith('edx.devstack.studio:') or hostname.startswith('studio.devstack.edx:'):
return False
return True
################################ MILESTONES ################################
FEATURES['MILESTONES_APP'] = True
########################### ORGANIZATIONS #################################
# Although production studio.edx.org disables `ORGANIZATIONS_AUTOCREATE`,
# we purposefully leave auto-creation enabled in Devstack Studio for developer
# convenience, allowing devs to create test courses for any organization
# without having to first manually create said organizations in the admin panel.
ORGANIZATIONS_AUTOCREATE = True
################################ ENTRANCE EXAMS ################################
FEATURES['ENTRANCE_EXAMS'] = True
################################ COURSE LICENSES ################################
FEATURES['LICENSING'] = True
# Needed to enable licensing on video blocks
XBLOCK_SETTINGS.update({'VideoBlock': {'licensing_enabled': True}})
################################ SEARCH INDEX ################################
FEATURES['ENABLE_COURSEWARE_INDEX'] = True
FEATURES['ENABLE_LIBRARY_INDEX'] = False
SEARCH_ENGINE = "search.elastic.ElasticSearchEngine"
ELASTIC_SEARCH_CONFIG = [
{
'use_ssl': False,
'host': 'edx.devstack.elasticsearch710',
'port': 9200
}
]
################################ COURSE DISCUSSIONS ###########################
FEATURES['ENABLE_DISCUSSION_SERVICE'] = True
################################ CREDENTIALS ###########################
CREDENTIALS_SERVICE_USERNAME = 'credentials_worker'
########################## Certificates Web/HTML View #######################
FEATURES['CERTIFICATES_HTML_VIEW'] = True
########################## AUTHOR PERMISSION #######################
FEATURES['ENABLE_CREATOR_GROUP'] = True
########################## Library creation organizations restriction #######################
FEATURES['ENABLE_ORGANIZATION_STAFF_ACCESS_FOR_CONTENT_LIBRARIES'] = True
################### FRONTEND APPLICATION PUBLISHER URL ###################
FEATURES['FRONTEND_APP_PUBLISHER_URL'] = 'http://localhost:18400'
################### FRONTEND APPLICATION LIBRARY AUTHORING ###################
LIBRARY_AUTHORING_MICROFRONTEND_URL = 'http://localhost:3001'
################### FRONTEND APPLICATION COURSE AUTHORING ###################
COURSE_AUTHORING_MICROFRONTEND_URL = 'http://localhost:2001'
################### FRONTEND APPLICATION DISCUSSIONS ###################
DISCUSSIONS_MICROFRONTEND_URL = 'http://localhost:2002'
################### FRONTEND APPLICATION DISCUSSIONS FEEDBACK URL###################
DISCUSSIONS_MFE_FEEDBACK_URL = None
################################# DJANGO-REQUIRE ###############################
# Whether to run django-require in debug mode.
REQUIRE_DEBUG = DEBUG
########################### OAUTH2 #################################
JWT_AUTH.update({
'JWT_ISSUER': f'{LMS_ROOT_URL}/oauth2',
'JWT_ISSUERS': [{
'AUDIENCE': 'lms-key',
'ISSUER': f'{LMS_ROOT_URL}/oauth2',
'SECRET_KEY': 'lms-secret',
}],
'JWT_SECRET_KEY': 'lms-secret',
'JWT_AUDIENCE': 'lms-key',
'JWT_PUBLIC_SIGNING_JWK_SET': (
'{"keys": [{"kid": "devstack_key", "e": "AQAB", "kty": "RSA", "n": "smKFSYowG6nNUAdeqH1jQQnH1PmIHphzBmwJ5vRf1vu'
'48BUI5VcVtUWIPqzRK_LDSlZYh9D0YFL0ZTxIrlb6Tn3Xz7pYvpIAeYuQv3_H5p8tbz7Fb8r63c1828wXPITVTv8f7oxx5W3lFFgpFAyYMmROC'
'4Ee9qG5T38LFe8_oAuFCEntimWxN9F3P-FJQy43TL7wG54WodgiM0EgzkeLr5K6cDnyckWjTuZbWI-4ffcTgTZsL_Kq1owa_J2ngEfxMCObnzG'
'y5ZLcTUomo4rZLjghVpq6KZxfS6I1Vz79ZsMVUWEdXOYePCKKsrQG20ogQEkmTf9FT_SouC6jPcHLXw"}]}'
),
})
# pylint: enable=unicode-format-string # lint-amnesty, pylint: disable=bad-option-value
IDA_LOGOUT_URI_LIST = [
'http://localhost:18130/logout/', # ecommerce
'http://localhost:18150/logout/', # credentials
]
ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_PROVIDER_URL = "http://edx.devstack.lms/oauth2"
#####################################################################
# pylint: disable=wrong-import-order, wrong-import-position
from edx_django_utils.plugins import add_plugins
# pylint: disable=wrong-import-order, wrong-import-position
from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType
add_plugins(__name__, ProjectType.CMS, SettingsType.DEVSTACK)
OPENAPI_CACHE_TIMEOUT = 0
#####################################################################
# set replica set of contentstore to none as we haven't setup any for cms in devstack
CONTENTSTORE['DOC_STORE_CONFIG']['replicaSet'] = None
#####################################################################
# set replica sets of moduelstore to none as we haven't setup any for cms in devstack
for store in MODULESTORE['default']['OPTIONS']['stores']:
if 'DOC_STORE_CONFIG' in store and 'replicaSet' in store['DOC_STORE_CONFIG']:
store['DOC_STORE_CONFIG']['replicaSet'] = None
#####################################################################
# Lastly, run any migrations, if needed.
MODULESTORE = convert_module_store_setting_if_needed(MODULESTORE)
# Dummy secret key for dev
SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd'
############# CORS headers for cross-domain requests #################
FEATURES['ENABLE_CORS_HEADERS'] = True
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
################### Special Exams (Proctoring) and Prereqs ###################
FEATURES['ENABLE_SPECIAL_EXAMS'] = True
FEATURES['ENABLE_PREREQUISITE_COURSES'] = True
# Used in edx-proctoring for ID generation in lieu of SECRET_KEY - dummy value
# (ref MST-637)
PROCTORING_USER_OBFUSCATION_KEY = '85920908f28904ed733fe576320db18cabd7b6cd'
#################### Webpack Configuration Settings ##############################
WEBPACK_LOADER['DEFAULT']['TIMEOUT'] = 5
################ Using LMS SSO for login to Studio ################
SOCIAL_AUTH_EDX_OAUTH2_KEY = 'studio-sso-key'
SOCIAL_AUTH_EDX_OAUTH2_SECRET = 'studio-sso-secret' # in stage, prod would be high-entropy secret
SOCIAL_AUTH_EDX_OAUTH2_URL_ROOT = 'http://edx.devstack.lms:18000' # routed internally server-to-server
SOCIAL_AUTH_EDX_OAUTH2_PUBLIC_URL_ROOT = 'http://localhost:18000' # used in browser redirect
# Don't form the return redirect URL with HTTPS on devstack
SOCIAL_AUTH_REDIRECT_IS_HTTPS = False
#################### Network configuration ####################
# Devstack is directly exposed to the caller
CLOSEST_CLIENT_IP_FROM_HEADERS = []
#################### Credentials Settings ####################
CREDENTIALS_INTERNAL_SERVICE_URL = 'http://edx.devstack.credentials:18150'
CREDENTIALS_PUBLIC_SERVICE_URL = 'http://localhost:18150'
########################## ORA MFE APP ##############################
ORA_MICROFRONTEND_URL = 'http://localhost:1992'
############################ AI_TRANSLATIONS ##################################
AI_TRANSLATIONS_API_URL = 'http://localhost:18760/api/v1'
############################ CSRF ##################################
# MFEs that will call this service in devstack
CSRF_TRUSTED_ORIGINS = [
'http://localhost:3001', # frontend-app-library-authoring
'http://localhost:2001', # frontend-app-course-authoring
'http://localhost:1992', # frontend-app-ora
'http://localhost:1999', # frontend-app-authn
]
#################### Event bus backend ########################
EVENT_BUS_PRODUCER = 'edx_event_bus_redis.create_producer'
EVENT_BUS_REDIS_CONNECTION_URL = 'redis://:password@edx.devstack.redis:6379/'
EVENT_BUS_TOPIC_PREFIX = 'dev'
EVENT_BUS_CONSUMER = 'edx_event_bus_redis.RedisEventConsumer'
course_catalog_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.course.catalog_info.changed.v1']
course_catalog_event_setting['course-catalog-info-changed']['enabled'] = True
xblock_published_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.xblock.published.v1']
xblock_published_event_setting['course-authoring-xblock-lifecycle']['enabled'] = True
xblock_deleted_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.xblock.deleted.v1']
xblock_deleted_event_setting['course-authoring-xblock-lifecycle']['enabled'] = True
xblock_duplicated_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.xblock.duplicated.v1']
xblock_duplicated_event_setting['course-authoring-xblock-lifecycle']['enabled'] = True
################# New settings must go ABOVE this line #################
########################################################################
# See if the developer has any local overrides.
if os.path.isfile(join(dirname(abspath(__file__)), 'private.py')):
from .private import * # pylint: disable=import-error,wildcard-import
############## Authoring API drf-spectacular openapi settings ##############
# These fields override the spectacular settings default values.
# Any fields not included here will use the default values.
SPECTACULAR_SETTINGS = {
'TITLE': 'Authoring API',
'DESCRIPTION': f'''Experimental API to edit xblocks and course content.
\n\nDanger: Do not use on running courses!
\n\n - How to gain access: Please email the owners of this openedx service.
\n - How to use: This API uses oauth2 authentication with the
access token endpoint: `{LMS_ROOT_URL}/oauth2/access_token`.
Please see separately provided documentation.
\n - How to test: You must be logged in as course author for whatever course you want to test with.
You can use the [Swagger UI](https://{CMS_BASE}/authoring-api/ui/) to "Try out" the API with your test course. To do this, you must select the "Local" server.
\n - Public vs. Local servers: The "Public" server is where you can reach the API externally. The "Local" server is
for development with a local edx-platform version, and for use via the [Swagger UI](https://{CMS_BASE}/authoring-api/ui/).
\n - Swaggerfile: [Download link](https://{CMS_BASE}/authoring-api/schema/)''',
'VERSION': '0.1.0',
'SERVE_INCLUDE_SCHEMA': False,
# restrict spectacular to CMS API endpoints (cms/lib/spectacular.py):
'PREPROCESSING_HOOKS': ['cms.lib.spectacular.cms_api_filter'],
# remove the default schema path prefix to replace it with server-specific base paths:
'SCHEMA_PATH_PREFIX': '/api/contentstore',
'SCHEMA_PATH_PREFIX_TRIM': '/api/contentstore',
'SERVERS': [
{'url': AUTHORING_API_URL, 'description': 'Public'},
{'url': f'http://{CMS_BASE}/api/contentstore', 'description': 'Local'}
],
}