Files
edx-platform/cms/urls.py
David Ormsbee 5d1b24988e Create learning_sequences app, Course Outline API.
Introduces the learning_sequences app, intended to provide metadata for
sequences and course outlines. The short term goal is to provide faster
source of this information for the new Courseware microfrontend
(frontend-app-learning). The medium term goal is to provide an in-proc
API that is useful to other parts of the platform that need fast access
to course outline information customized for a user. The long term
goals are outlined in the README.rst.

This first iteration of the API only lays out the basic structure for
how we'd arrange the pieces, with enough of an implementation to feel
"real" (simple schedules, staff_only content hiding). It's not ready to
be turned on, and is not currently plugged into the publish-flow. The
only way to get data into this new API is via the update_course_outline
management command. The REST endpoint is also currently limited to
global staff only, though it's possible to get the outline for a student
by using the ?username= query parameter.

TNL-7122
2020-06-02 15:31:21 -04:00

303 lines
15 KiB
Python

"""
Urls of Studio.
"""
from django.conf import settings
from django.conf.urls import include, url
from django.conf.urls.static import static
from django.contrib.admin import autodiscover as django_autodiscover
from django.utils.translation import ugettext_lazy as _
from edx_api_doc_tools import make_docs_urls
from ratelimitbackend import admin
import contentstore.views
import openedx.core.djangoapps.common_views.xblock
import openedx.core.djangoapps.debug.views
import openedx.core.djangoapps.lang_pref.views
from cms.djangoapps.contentstore.views.organization import OrganizationListView
from openedx.core.djangoapps.password_policy import compliance as password_policy_compliance
from openedx.core.djangoapps.password_policy.forms import PasswordPolicyAwareAdminAuthForm
from openedx.core.apidocs import api_info
django_autodiscover()
admin.site.site_header = _('Studio Administration')
admin.site.site_title = admin.site.site_header
if password_policy_compliance.should_enforce_compliance_on_login():
admin.site.login_form = PasswordPolicyAwareAdminAuthForm
# Custom error pages
# These are used by Django to render these error codes. Do not remove.
# pylint: disable=invalid-name
handler404 = contentstore.views.render_404
handler500 = contentstore.views.render_500
# Pattern to match a course key or a library key
COURSELIKE_KEY_PATTERN = r'(?P<course_key_string>({}|{}))'.format(
r'[^/]+/[^/]+/[^/]+', r'[^/:]+:[^/+]+\+[^/+]+(\+[^/]+)?'
)
# Pattern to match a library key only
LIBRARY_KEY_PATTERN = r'(?P<library_key_string>library-v1:[^/+]+\+[^/+]+)'
urlpatterns = [
url(r'', include('openedx.core.djangoapps.user_authn.urls_common')),
url(r'', include('student.urls')),
url(r'^transcripts/upload$', contentstore.views.upload_transcripts, name='upload_transcripts'),
url(r'^transcripts/download$', contentstore.views.download_transcripts, name='download_transcripts'),
url(r'^transcripts/check$', contentstore.views.check_transcripts, name='check_transcripts'),
url(r'^transcripts/choose$', contentstore.views.choose_transcripts, name='choose_transcripts'),
url(r'^transcripts/replace$', contentstore.views.replace_transcripts, name='replace_transcripts'),
url(r'^transcripts/rename$', contentstore.views.rename_transcripts, name='rename_transcripts'),
url(r'^preview/xblock/(?P<usage_key_string>.*?)/handler/(?P<handler>[^/]*)(?:/(?P<suffix>.*))?$',
contentstore.views.preview_handler, name='preview_handler'),
url(r'^xblock/(?P<usage_key_string>.*?)/handler/(?P<handler>[^/]*)(?:/(?P<suffix>.*))?$',
contentstore.views.component_handler, name='component_handler'),
url(r'^xblock/resource/(?P<block_type>[^/]*)/(?P<uri>.*)$',
openedx.core.djangoapps.common_views.xblock.xblock_resource, name='xblock_resource_url'),
url(r'', include('openedx.core.djangoapps.xblock.rest_api.urls', namespace='xblock_api')),
url(r'^not_found$', contentstore.views.not_found, name='not_found'),
url(r'^server_error$', contentstore.views.server_error, name='server_error'),
url(r'^organizations$', OrganizationListView.as_view(), name='organizations'),
# noop to squelch ajax errors
url(r'^event$', contentstore.views.event, name='event'),
url(r'^heartbeat', include('openedx.core.djangoapps.heartbeat.urls')),
url(r'^i18n/', include('django.conf.urls.i18n')),
# User API endpoints
url(r'^api/user/', include('openedx.core.djangoapps.user_api.urls')),
# Update session view
url(r'^lang_pref/session_language',
openedx.core.djangoapps.lang_pref.views.update_session_language,
name='session_language'
),
# Darklang View to change the preview language (or dark language)
url(r'^update_lang/', include('openedx.core.djangoapps.dark_lang.urls', namespace='dark_lang')),
# For redirecting to help pages.
url(r'^help_token/', include('help_tokens.urls')),
url(r'^api/', include('cms.djangoapps.api.urls', namespace='api')),
# restful api
url(r'^$', contentstore.views.howitworks, name='homepage'),
url(r'^howitworks$', contentstore.views.howitworks, name='howitworks'),
url(r'^signin_redirect_to_lms$', contentstore.views.login_redirect_to_lms, name='login_redirect_to_lms'),
url(r'^request_course_creator$', contentstore.views.request_course_creator, name='request_course_creator'),
url(r'^course_team/{}(?:/(?P<email>.+))?$'.format(COURSELIKE_KEY_PATTERN),
contentstore.views.course_team_handler, name='course_team_handler'),
url(r'^course_info/{}$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.course_info_handler,
name='course_info_handler'),
url(r'^course_info_update/{}/(?P<provided_id>\d+)?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.course_info_update_handler, name='course_info_update_handler'
),
url(r'^home/?$', contentstore.views.course_listing, name='home'),
url(r'^course/{}/search_reindex?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.course_search_index_handler,
name='course_search_index_handler'
),
url(r'^course/{}?$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.course_handler, name='course_handler'),
url(r'^checklists/{}?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.checklists_handler,
name='checklists_handler'),
url(r'^course_notifications/{}/(?P<action_state_id>\d+)?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.course_notifications_handler,
name='course_notifications_handler'),
url(r'^course_rerun/{}$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.course_rerun_handler,
name='course_rerun_handler'),
url(r'^container/{}$'.format(settings.USAGE_KEY_PATTERN), contentstore.views.container_handler,
name='container_handler'),
url(r'^orphan/{}$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.orphan_handler,
name='orphan_handler'),
url(r'^assets/{}/{}?$'.format(settings.COURSE_KEY_PATTERN, settings.ASSET_KEY_PATTERN),
contentstore.views.assets_handler,
name='assets_handler'),
url(r'^import/{}$'.format(COURSELIKE_KEY_PATTERN), contentstore.views.import_handler,
name='import_handler'),
url(r'^import_status/{}/(?P<filename>.+)$'.format(COURSELIKE_KEY_PATTERN),
contentstore.views.import_status_handler, name='import_status_handler'),
# rest api for course import/export
url(r'^api/courses/',
include('cms.djangoapps.contentstore.api.urls', namespace='courses_api')
),
url(r'^export/{}$'.format(COURSELIKE_KEY_PATTERN), contentstore.views.export_handler,
name='export_handler'),
url(r'^export_output/{}$'.format(COURSELIKE_KEY_PATTERN), contentstore.views.export_output_handler,
name='export_output_handler'),
url(r'^export_status/{}$'.format(COURSELIKE_KEY_PATTERN), contentstore.views.export_status_handler,
name='export_status_handler'),
url(r'^xblock/outline/{}$'.format(settings.USAGE_KEY_PATTERN), contentstore.views.xblock_outline_handler,
name='xblock_outline_handler'),
url(r'^xblock/container/{}$'.format(settings.USAGE_KEY_PATTERN), contentstore.views.xblock_container_handler,
name='xblock_container_handler'),
url(r'^xblock/{}/(?P<view_name>[^/]+)$'.format(settings.USAGE_KEY_PATTERN), contentstore.views.xblock_view_handler,
name='xblock_view_handler'),
url(r'^xblock/{}?$'.format(settings.USAGE_KEY_PATTERN), contentstore.views.xblock_handler,
name='xblock_handler'),
url(r'^tabs/{}$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.tabs_handler,
name='tabs_handler'),
url(r'^settings/details/{}$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.settings_handler,
name='settings_handler'),
url(r'^settings/grading/{}(/)?(?P<grader_index>\d+)?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.grading_handler, name='grading_handler'),
url(r'^settings/advanced/{}$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.advanced_settings_handler,
name='advanced_settings_handler'),
url(r'^textbooks/{}$'.format(settings.COURSE_KEY_PATTERN), contentstore.views.textbooks_list_handler,
name='textbooks_list_handler'),
url(r'^textbooks/{}/(?P<textbook_id>\d[^/]*)$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.textbooks_detail_handler, name='textbooks_detail_handler'),
url(r'^videos/{}(?:/(?P<edx_video_id>[-\w]+))?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.videos_handler, name='videos_handler'),
url(r'^video_images/{}(?:/(?P<edx_video_id>[-\w]+))?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.video_images_handler, name='video_images_handler'),
url(r'^transcript_preferences/{}$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.transcript_preferences_handler, name='transcript_preferences_handler'),
url(r'^transcript_credentials/{}$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.transcript_credentials_handler, name='transcript_credentials_handler'),
url(r'^transcript_download/$', contentstore.views.transcript_download_handler, name='transcript_download_handler'),
url(r'^transcript_upload/$', contentstore.views.transcript_upload_handler, name='transcript_upload_handler'),
url(r'^transcript_delete/{}(?:/(?P<edx_video_id>[-\w]+))?(?:/(?P<language_code>[^/]*))?$'.format(
settings.COURSE_KEY_PATTERN
), contentstore.views.transcript_delete_handler, name='transcript_delete_handler'),
url(r'^video_encodings_download/{}$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.video_encodings_download, name='video_encodings_download'),
url(r'^group_configurations/{}$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.group_configurations_list_handler,
name='group_configurations_list_handler'),
url(r'^group_configurations/{}/(?P<group_configuration_id>\d+)(/)?(?P<group_id>\d+)?$'.format(
settings.COURSE_KEY_PATTERN), contentstore.views.group_configurations_detail_handler,
name='group_configurations_detail_handler'),
url(r'^api/val/v0/', include('edxval.urls')),
url(r'^api/tasks/v0/', include('user_tasks.urls')),
url(r'^accessibility$', contentstore.views.accessibility, name='accessibility'),
]
if not settings.DISABLE_DEPRECATED_SIGNIN_URL:
# TODO: Remove deprecated signin url when traffic proves it is no longer in use
urlpatterns += [
url(r'^signin$', contentstore.views.login_redirect_to_lms),
]
if not settings.DISABLE_DEPRECATED_SIGNUP_URL:
# TODO: Remove deprecated signup url when traffic proves it is no longer in use
urlpatterns += [
url(r'^signup$', contentstore.views.register_redirect_to_lms, name='register_redirect_to_lms'),
]
JS_INFO_DICT = {
'domain': 'djangojs',
# We need to explicitly include external Django apps that are not in LOCALE_PATHS.
'packages': ('openassessment',),
}
if settings.FEATURES.get('ENABLE_CONTENT_LIBRARIES'):
urlpatterns += [
url(r'^library/{}?$'.format(LIBRARY_KEY_PATTERN),
contentstore.views.library_handler, name='library_handler'),
url(r'^library/{}/team/$'.format(LIBRARY_KEY_PATTERN),
contentstore.views.manage_library_users, name='manage_library_users'),
]
if settings.FEATURES.get('ENABLE_EXPORT_GIT'):
urlpatterns += [
url(r'^export_git/{}$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.export_git,
name='export_git')
]
if settings.FEATURES.get('ENABLE_SERVICE_STATUS'):
urlpatterns.append(url(r'^status/', include('openedx.core.djangoapps.service_status.urls')))
# The password pages in the admin tool are disabled so that all password
# changes go through our user portal and follow complexity requirements.
if not settings.FEATURES.get('ENABLE_CHANGE_USER_PASSWORD_ADMIN'):
urlpatterns.append(url(r'^admin/auth/user/\d+/password/$', handler404))
urlpatterns.append(url(r'^admin/password_change/$', handler404))
urlpatterns.append(url(r'^admin/', admin.site.urls))
# enable entrance exams
if settings.FEATURES.get('ENTRANCE_EXAMS'):
urlpatterns.append(url(r'^course/{}/entrance_exam/?$'.format(settings.COURSE_KEY_PATTERN),
contentstore.views.entrance_exam))
# Enable Web/HTML Certificates
if settings.FEATURES.get('CERTIFICATES_HTML_VIEW'):
from contentstore.views.certificates import (
certificate_activation_handler,
signatory_detail_handler,
certificates_detail_handler,
certificates_list_handler
)
urlpatterns += [
url(r'^certificates/activation/{}/'.format(settings.COURSE_KEY_PATTERN),
certificate_activation_handler,
name='certificate_activation_handler'),
url(r'^certificates/{}/(?P<certificate_id>\d+)/signatories/(?P<signatory_id>\d+)?$'.format(
settings.COURSE_KEY_PATTERN), signatory_detail_handler, name='signatory_detail_handler'),
url(r'^certificates/{}/(?P<certificate_id>\d+)?$'.format(settings.COURSE_KEY_PATTERN),
certificates_detail_handler, name='certificates_detail_handler'),
url(r'^certificates/{}$'.format(settings.COURSE_KEY_PATTERN),
certificates_list_handler, name='certificates_list_handler')
]
# Maintenance Dashboard
urlpatterns.append(url(r'^maintenance/', include('maintenance.urls', namespace='maintenance')))
if settings.DEBUG:
try:
from .urls_dev import urlpatterns as dev_urlpatterns
urlpatterns += dev_urlpatterns
except ImportError:
pass
urlpatterns += static(
settings.VIDEO_IMAGE_SETTINGS['STORAGE_KWARGS']['base_url'],
document_root=settings.VIDEO_IMAGE_SETTINGS['STORAGE_KWARGS']['location']
)
urlpatterns += static(
settings.VIDEO_TRANSCRIPTS_SETTINGS['STORAGE_KWARGS']['base_url'],
document_root=settings.VIDEO_TRANSCRIPTS_SETTINGS['STORAGE_KWARGS']['location']
)
if 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar
urlpatterns.append(url(r'^__debug__/', include(debug_toolbar.urls)))
# UX reference templates
urlpatterns.append(url(r'^template/(?P<template>.+)$', openedx.core.djangoapps.debug.views.show_reference_template,
name='openedx.core.djangoapps.debug.views.show_reference_template'))
urlpatterns.append(
url(
r'^api/learning_sequences/',
include(
('openedx.core.djangoapps.content.learning_sequences.urls', 'learning_sequences'),
namespace='learning_sequences'
),
),
)
# display error page templates, for testing purposes
urlpatterns += [
url(r'^404$', handler404),
url(r'^500$', handler500),
]
# API docs.
urlpatterns += make_docs_urls(api_info)
if 'openedx.testing.coverage_context_listener' in settings.INSTALLED_APPS:
urlpatterns += [
url(r'coverage_context', include('openedx.testing.coverage_context_listener.urls'))
]
from openedx.core.djangoapps.plugins import constants as plugin_constants, plugin_urls
urlpatterns.extend(plugin_urls.get_patterns(plugin_constants.ProjectType.CMS))